1use eetf::Term;
2use num_bigint::BigInt;
3use std::cmp::Ordering;
4
5#[inline]
7pub fn u64_to_term(value: u64) -> Term {
8 if value <= i32::MAX as u64 {
9 Term::FixInteger(eetf::FixInteger { value: value as i32 })
10 } else {
11 Term::BigInteger(eetf::BigInteger::from(value))
12 }
13}
14
15#[inline]
16pub fn i64_to_term(value: i64) -> Term {
17 if value <= i32::MAX as i64 {
18 Term::FixInteger(eetf::FixInteger { value: value as i32 })
19 } else {
20 Term::BigInteger(eetf::BigInteger::from(value))
21 }
22}
23
24#[inline]
26pub fn i128_to_term(value: i128) -> Term {
27 if value >= i32::MIN as i128 && value <= i32::MAX as i128 {
28 Term::FixInteger(eetf::FixInteger { value: value as i32 })
29 } else if value >= 0 && value <= u64::MAX as i128 {
30 Term::BigInteger(eetf::BigInteger::from(value as u64))
31 } else {
32 Term::BigInteger(eetf::BigInteger { value: BigInt::from(value) })
34 }
35}
36
37#[inline]
39pub fn u32_to_term(value: u32) -> Term {
40 if value <= i32::MAX as u32 {
41 Term::FixInteger(eetf::FixInteger { value: value as i32 })
42 } else {
43 Term::BigInteger(eetf::BigInteger::from(value as u64))
44 }
45}
46
47#[inline]
49pub fn i32_to_term(value: i32) -> Term {
50 Term::FixInteger(eetf::FixInteger { value })
51}
52
53pub fn encode_safe(term: &Term) -> Vec<u8> {
56 let mut buf = Vec::new();
57 buf.push(131); encode_term_with_small_atoms(term, &mut buf);
59 buf
60}
61
62pub fn encode_safe_deterministic(term: &Term) -> Vec<u8> {
64 let mut buf = Vec::new();
65 buf.push(131); encode_map_safe_deterministic(term, &mut buf);
67 buf
68}
69
70fn compare_terms(a: &Term, b: &Term) -> Ordering {
72 let type_order = |term: &Term| -> u8 {
73 match term {
74 Term::FixInteger(_) | Term::BigInteger(_) | Term::Float(_) => 1,
75 Term::Atom(_) => 2,
76 Term::Reference(_) => 3,
77 Term::Port(_) => 4,
78 Term::Pid(_) => 5,
79 Term::Tuple(_) => 6,
80 Term::Map(_) => 7,
81 Term::List(_) | Term::ImproperList(_) => 8,
82 Term::Binary(_) | Term::BitBinary(_) | Term::ByteList(_) => 9,
83 Term::ExternalFun(_) | Term::InternalFun(_) => 10,
84 }
85 };
86
87 let a_type = type_order(a);
88 let b_type = type_order(b);
89
90 match a_type.cmp(&b_type) {
91 Ordering::Equal => {
92 match (a, b) {
93 (Term::FixInteger(a_int), Term::FixInteger(b_int)) => a_int.value.cmp(&b_int.value),
96 (Term::BigInteger(a_big), Term::BigInteger(b_big)) => a_big.value.cmp(&b_big.value),
97 (Term::Float(a_float), Term::Float(b_float)) => {
98 a_float.value.partial_cmp(&b_float.value).unwrap_or(Ordering::Equal)
99 }
100
101 (Term::FixInteger(_), Term::Float(_)) => Ordering::Less,
103 (Term::Float(_), Term::FixInteger(_)) => Ordering::Greater,
104 (Term::BigInteger(_), Term::Float(_)) => Ordering::Less,
105 (Term::Float(_), Term::BigInteger(_)) => Ordering::Greater,
106 (Term::FixInteger(_), Term::BigInteger(_)) => Ordering::Less,
108 (Term::BigInteger(_), Term::FixInteger(_)) => Ordering::Greater,
109
110 (Term::Atom(a_atom), Term::Atom(b_atom)) => a_atom.name.cmp(&b_atom.name),
111
112 (Term::Binary(a_bin), Term::Binary(b_bin)) => a_bin.bytes.cmp(&b_bin.bytes),
114 (Term::ByteList(a_bytes), Term::ByteList(b_bytes)) => a_bytes.bytes.cmp(&b_bytes.bytes),
115
116 _ => format!("{:?}", a).cmp(&format!("{:?}", b)),
118 }
119 }
120 other => other,
121 }
122}
123
124fn encode_map_safe_deterministic(term: &Term, buf: &mut Vec<u8>) {
126 match term {
127 Term::Map(map) => {
128 let mut sorted_pairs: Vec<_> = map.map.iter().collect();
129 sorted_pairs.sort_by(|(a, _), (b, _)| compare_terms(a, b));
130
131 buf.push(116); buf.extend_from_slice(&(sorted_pairs.len() as u32).to_be_bytes());
133
134 for (key, value) in sorted_pairs {
135 encode_map_safe_deterministic(key, buf);
136 encode_map_safe_deterministic(value, buf);
137 }
138 }
139 _ => {
140 encode_term_safe_deterministic(term, buf);
142 }
143 }
144}
145
146fn encode_term_safe_deterministic(term: &Term, buf: &mut Vec<u8>) {
148 match term {
149 Term::Atom(atom) => {
150 let name_bytes = atom.name.as_bytes();
151 if name_bytes.len() <= 255 {
152 buf.push(119); buf.push(name_bytes.len() as u8);
154 buf.extend_from_slice(name_bytes);
155 } else {
156 buf.push(118); buf.extend_from_slice(&(name_bytes.len() as u16).to_be_bytes());
158 buf.extend_from_slice(name_bytes);
159 }
160 }
161 Term::List(list) => {
162 if list.elements.is_empty() {
163 buf.push(106); } else {
165 buf.push(108); buf.extend_from_slice(&(list.elements.len() as u32).to_be_bytes());
167 for element in &list.elements {
168 encode_map_safe_deterministic(element, buf); }
170 buf.push(106); }
172 }
173 Term::ImproperList(improper) => {
174 buf.push(108); buf.extend_from_slice(&(improper.elements.len() as u32).to_be_bytes());
176 for element in &improper.elements {
177 encode_map_safe_deterministic(element, buf); }
179 encode_map_safe_deterministic(&improper.last, buf); }
181 Term::Tuple(tuple) => {
182 if tuple.elements.len() <= 255 {
183 buf.push(104); buf.push(tuple.elements.len() as u8);
185 } else {
186 buf.push(105); buf.extend_from_slice(&(tuple.elements.len() as u32).to_be_bytes());
188 }
189 for element in &tuple.elements {
190 encode_map_safe_deterministic(element, buf); }
192 }
193 Term::Map(_map) => {
194 encode_map_safe_deterministic(term, buf);
197 }
198 _ => {
199 encode_term_with_small_atoms(term, buf);
201 }
202 }
203}
204
205fn encode_term_with_small_atoms(term: &Term, buf: &mut Vec<u8>) {
206 match term {
207 Term::Atom(atom) => {
208 let name_bytes = atom.name.as_bytes();
210 if name_bytes.len() <= 255 {
211 buf.push(119); buf.push(name_bytes.len() as u8);
213 buf.extend_from_slice(name_bytes);
214 } else {
215 buf.push(118); buf.extend_from_slice(&(name_bytes.len() as u16).to_be_bytes());
218 buf.extend_from_slice(name_bytes);
219 }
220 }
221 Term::Binary(binary) => {
222 buf.push(109); buf.extend_from_slice(&(binary.bytes.len() as u32).to_be_bytes());
224 buf.extend_from_slice(&binary.bytes);
225 }
226 Term::FixInteger(fix_int) => {
227 if fix_int.value >= 0 && fix_int.value <= 255 {
228 buf.push(97); buf.push(fix_int.value as u8);
230 } else {
231 buf.push(98); buf.extend_from_slice(&fix_int.value.to_be_bytes());
233 }
234 }
235 Term::BigInteger(big_int) => {
236 let bytes = big_int.value.to_bytes_le().1;
238 if bytes.len() <= 255 {
239 buf.push(110); buf.push(bytes.len() as u8);
241 buf.push(if big_int.value >= 0.into() { 0 } else { 1 }); } else {
243 buf.push(111); buf.extend_from_slice(&(bytes.len() as u32).to_be_bytes());
245 buf.push(if big_int.value >= 0.into() { 0 } else { 1 }); }
247 buf.extend_from_slice(&bytes);
248 }
249 Term::List(list) => {
250 if list.elements.is_empty() {
251 buf.push(106); } else {
253 buf.push(108); buf.extend_from_slice(&(list.elements.len() as u32).to_be_bytes());
255 for element in &list.elements {
256 encode_term_with_small_atoms(element, buf);
257 }
258 buf.push(106); }
260 }
261 Term::ImproperList(improper) => {
262 buf.push(108); buf.extend_from_slice(&(improper.elements.len() as u32).to_be_bytes());
264 for element in &improper.elements {
265 encode_term_with_small_atoms(element, buf);
266 }
267 encode_term_with_small_atoms(&improper.last, buf); }
269 Term::Tuple(tuple) => {
270 if tuple.elements.len() <= 255 {
271 buf.push(104); buf.push(tuple.elements.len() as u8);
273 } else {
274 buf.push(105); buf.extend_from_slice(&(tuple.elements.len() as u32).to_be_bytes());
276 }
277 for element in &tuple.elements {
278 encode_term_with_small_atoms(element, buf);
279 }
280 }
281 Term::Map(map) => {
282 buf.push(116); buf.extend_from_slice(&(map.map.len() as u32).to_be_bytes());
284 for (key, value) in &map.map {
285 encode_term_with_small_atoms(key, buf);
286 encode_term_with_small_atoms(value, buf);
287 }
288 }
289 Term::Pid(pid) => {
290 buf.push(103); encode_term_with_small_atoms(&Term::Atom(pid.node.clone()), buf);
292 buf.extend_from_slice(&pid.id.to_be_bytes());
293 buf.extend_from_slice(&pid.serial.to_be_bytes());
294 buf.push(pid.creation.try_into().unwrap());
295 }
296 Term::Port(port) => {
297 buf.push(102); encode_term_with_small_atoms(&Term::Atom(port.node.clone()), buf);
299 buf.extend_from_slice(&port.id.to_be_bytes());
300 buf.push(port.creation.try_into().unwrap());
301 }
302 Term::Reference(reference) => {
303 buf.push(114); buf.extend_from_slice(&(reference.id.len() as u16).to_be_bytes());
305 encode_term_with_small_atoms(&Term::Atom(reference.node.clone()), buf);
306 buf.push(reference.creation.try_into().unwrap());
307 for id in &reference.id {
308 buf.extend_from_slice(&id.to_be_bytes());
309 }
310 }
311 Term::ExternalFun(ext_fun) => {
312 buf.push(113); encode_term_with_small_atoms(&Term::Atom(ext_fun.module.clone()), buf);
314 encode_term_with_small_atoms(&Term::Atom(ext_fun.function.clone()), buf);
315 encode_term_with_small_atoms(&Term::FixInteger(eetf::FixInteger { value: ext_fun.arity as i32 }), buf);
316 }
317 Term::InternalFun(int_fun) => {
318 match int_fun.as_ref() {
319 eetf::InternalFun::Old { module, pid, free_vars, index, uniq } => {
320 buf.push(117); buf.extend_from_slice(&(*index as u32).to_be_bytes());
322 buf.extend_from_slice(&(*uniq as u32).to_be_bytes());
323 encode_term_with_small_atoms(&Term::Atom(module.clone()), buf);
324 encode_term_with_small_atoms(&Term::Pid(pid.clone()), buf);
325 for var in free_vars {
326 encode_term_with_small_atoms(var, buf);
327 }
328 }
329 eetf::InternalFun::New { module, arity, pid, free_vars, index, uniq, old_index, old_uniq } => {
330 buf.push(112); buf.push(*arity);
332 buf.extend_from_slice(uniq);
333 buf.extend_from_slice(&index.to_be_bytes());
334 buf.extend_from_slice(&(free_vars.len() as u32).to_be_bytes());
335 encode_term_with_small_atoms(&Term::Atom(module.clone()), buf);
336 encode_term_with_small_atoms(&Term::FixInteger(eetf::FixInteger { value: *old_index }), buf);
337 encode_term_with_small_atoms(&Term::FixInteger(eetf::FixInteger { value: *old_uniq }), buf);
338 encode_term_with_small_atoms(&Term::Pid(pid.clone()), buf);
339 for var in free_vars {
340 encode_term_with_small_atoms(var, buf);
341 }
342 }
343 }
344 }
345 Term::BitBinary(bit_binary) => {
346 buf.push(77); buf.extend_from_slice(&(bit_binary.bytes.len() as u32).to_be_bytes());
348 buf.push(bit_binary.tail_bits_size);
349 buf.extend_from_slice(&bit_binary.bytes);
350 }
351 Term::Float(float) => {
352 buf.push(70); buf.extend_from_slice(&float.value.to_be_bytes());
354 }
355 Term::ByteList(byte_list) => {
356 buf.push(107); buf.extend_from_slice(&(byte_list.bytes.len() as u16).to_be_bytes());
358 buf.extend_from_slice(&byte_list.bytes);
359 }
360 }
361}
362
363#[cfg(test)]
364mod tests {
365 use super::*;
366 use eetf::{Atom, FixInteger, Map};
367 use std::collections::HashMap;
368
369 #[test]
370 fn test_small_atom_encoding() {
371 let atom = Term::Atom(Atom::from("test"));
372 let encoded = encode_safe(&atom);
373
374 assert_eq!(encoded[0], 131); assert_eq!(encoded[1], 119); assert_eq!(encoded[2], 4); assert_eq!(&encoded[3..7], b"test");
379 }
380
381 #[test]
382 fn test_map_with_small_atoms() {
383 let mut map = HashMap::new();
384 map.insert(Term::Atom(Atom::from("key")), Term::Atom(Atom::from("value")));
385 let term_map = Term::Map(Map { map });
386
387 let encoded = encode_safe(&term_map);
388
389 assert_eq!(encoded[0], 131); assert_eq!(encoded[1], 116); assert!(encoded.contains(&119)); }
396
397 #[test]
398 fn test_big_integer_encoding() {
399 use eetf::BigInteger;
400
401 let test_values = vec![
403 2147483648u64, 4294967296u64, 1693958400u64, ];
407
408 for value in test_values {
409 let big_int_term = Term::BigInteger(BigInteger::from(value));
410
411 let mut original_encoded = Vec::new();
413 big_int_term.encode(&mut original_encoded).unwrap();
414
415 let our_encoded = encode_safe(&big_int_term);
417
418 assert_eq!(original_encoded, our_encoded, "Encoding mismatch for value {}", value);
420
421 let original_decoded = Term::decode(&original_encoded[..]).unwrap();
423 let our_decoded = Term::decode(&our_encoded[..]).unwrap();
424
425 if let (Term::BigInteger(orig), Term::BigInteger(ours)) = (&original_decoded, &our_decoded) {
426 assert_eq!(orig.value, ours.value, "BigInteger values should match for {}", value);
427 }
428 }
429 }
430
431 #[test]
432 fn test_compatibility_with_original() {
433 let atom = Term::Atom(Atom::from("test"));
436 let mut original_encoded = Vec::new();
437 atom.encode(&mut original_encoded).unwrap();
438 let our_encoded = encode_safe(&atom);
439
440 println!("Original: {:?}", original_encoded);
441 println!("Our: {:?}", our_encoded);
442
443 assert_eq!(original_encoded[0], our_encoded[0]); if original_encoded.len() == 8 && our_encoded.len() == 7 {
447 assert_eq!(original_encoded[1], 100); assert_eq!(our_encoded[1], 119); assert_eq!(original_encoded[2], 0); assert_eq!(original_encoded[3], 4); assert_eq!(our_encoded[2], 4); assert_eq!(original_encoded[4..], our_encoded[3..]);
460 } else {
461 assert_eq!(original_encoded.len(), our_encoded.len());
463 assert_eq!(original_encoded[1], 119); assert_eq!(our_encoded[1], 119); assert_eq!(original_encoded[2..], our_encoded[2..]);
466 }
467 }
468
469 #[test]
470 fn test_deterministic_encoding_mixed_key_types() {
471 let mut map_data = HashMap::new();
473
474 map_data.insert(Term::Atom(Atom::from("atom_key")), Term::FixInteger(FixInteger { value: 1 })); map_data.insert(
477 Term::Binary(eetf::Binary { bytes: b"binary_key".to_vec() }),
478 Term::FixInteger(FixInteger { value: 2 }),
479 ); map_data.insert(Term::FixInteger(FixInteger { value: 42 }), Term::FixInteger(FixInteger { value: 3 })); let map = Term::Map(Map { map: map_data });
483
484 let encoded = encode_safe_deterministic(&map);
486
487 assert_eq!(encoded[0], 131); assert_eq!(encoded[1], 116); let decoded = Term::decode(&encoded[..]).unwrap();
493 if let Term::Map(decoded_map) = decoded {
494 assert_eq!(decoded_map.map.len(), 3);
495
496 assert!(decoded_map.map.contains_key(&Term::FixInteger(FixInteger { value: 42 })));
498 assert!(decoded_map.map.contains_key(&Term::Atom(Atom::from("atom_key"))));
499 assert!(decoded_map.map.contains_key(&Term::Binary(eetf::Binary { bytes: b"binary_key".to_vec() })));
500 } else {
501 panic!("Decoded term is not a map");
502 }
503 }
504
505 #[test]
506 fn test_deterministic_encoding_atom_alphabetical_order() {
507 let mut map_data = HashMap::new();
509
510 map_data.insert(Term::Atom(Atom::from("zebra")), Term::FixInteger(FixInteger { value: 1 }));
512 map_data.insert(Term::Atom(Atom::from("apple")), Term::FixInteger(FixInteger { value: 2 }));
513 map_data.insert(Term::Atom(Atom::from("banana")), Term::FixInteger(FixInteger { value: 3 }));
514
515 let map = Term::Map(Map { map: map_data });
516
517 let encoded1 = encode_safe_deterministic(&map);
519 let encoded2 = encode_safe_deterministic(&map);
520
521 assert_eq!(encoded1, encoded2);
523
524 let decoded = Term::decode(&encoded1[..]).unwrap();
526 if let Term::Map(decoded_map) = decoded {
527 assert_eq!(decoded_map.map.len(), 3);
528 } else {
529 panic!("Decoded term is not a map");
530 }
531 }
532
533 #[test]
534 fn test_deterministic_encoding_number_ordering() {
535 let mut map_data = HashMap::new();
537
538 map_data.insert(Term::FixInteger(FixInteger { value: 100 }), Term::Atom(Atom::from("hundred")));
540 map_data.insert(Term::FixInteger(FixInteger { value: 5 }), Term::Atom(Atom::from("five")));
541 map_data.insert(Term::FixInteger(FixInteger { value: 50 }), Term::Atom(Atom::from("fifty")));
542
543 let map = Term::Map(Map { map: map_data });
544
545 let encoded = encode_safe_deterministic(&map);
546
547 let decoded = Term::decode(&encoded[..]).unwrap();
549 if let Term::Map(decoded_map) = decoded {
550 assert_eq!(decoded_map.map.len(), 3);
551 } else {
552 panic!("Decoded term is not a map");
553 }
554 }
555
556 #[test]
557 fn test_deterministic_vs_original_compatibility() {
558 let atom = Term::Atom(Atom::from("test_atom"));
560
561 let deterministic_encoded = encode_safe_deterministic(&atom);
562 let small_atoms_encoded = encode_safe(&atom);
563
564 assert_eq!(deterministic_encoded, small_atoms_encoded);
566
567 assert_eq!(deterministic_encoded[1], 119); assert_eq!(small_atoms_encoded[1], 119); }
571
572 #[test]
573 fn test_deterministic_encoding_anr_keys() {
574 let mut map_data = HashMap::new();
576
577 let anr_keys = ["ip4", "pk", "pop", "port", "signature", "ts", "version", "anr_name", "anr_desc"];
579 for (i, key) in anr_keys.iter().enumerate() {
580 map_data.insert(Term::Atom(Atom::from(*key)), Term::FixInteger(FixInteger { value: i as i32 }));
581 }
582
583 let map = Term::Map(Map { map: map_data });
584 let encoded = encode_safe_deterministic(&map);
585
586 let encoded2 = encode_safe_deterministic(&map);
588 assert_eq!(encoded, encoded2);
589
590 let decoded = Term::decode(&encoded[..]).unwrap();
592 if let Term::Map(decoded_map) = decoded {
593 assert_eq!(decoded_map.map.len(), anr_keys.len());
594
595 for key in &anr_keys {
597 assert!(decoded_map.map.contains_key(&Term::Atom(Atom::from(*key))));
598 }
599 } else {
600 panic!("Decoded term is not a map");
601 }
602 }
603
604 #[test]
605 fn test_deterministic_encoding_nested_structures() {
606 let mut inner_map = HashMap::new();
608 inner_map.insert(Term::Atom(Atom::from("z")), Term::FixInteger(FixInteger { value: 1 }));
609 inner_map.insert(Term::Atom(Atom::from("a")), Term::FixInteger(FixInteger { value: 2 }));
610
611 let mut outer_map = HashMap::new();
612 outer_map.insert(Term::Atom(Atom::from("nested")), Term::Map(Map { map: inner_map }));
613 outer_map.insert(
614 Term::Atom(Atom::from("list")),
615 Term::List(eetf::List {
616 elements: vec![Term::Atom(Atom::from("second")), Term::Atom(Atom::from("first"))],
617 }),
618 );
619
620 let map = Term::Map(Map { map: outer_map });
621
622 let encoded1 = encode_safe_deterministic(&map);
623 let encoded2 = encode_safe_deterministic(&map);
624
625 assert_eq!(encoded1, encoded2);
627
628 let decoded = Term::decode(&encoded1[..]).unwrap();
630 if let Term::Map(_) = decoded {
631 } else {
633 panic!("Decoded term is not a map");
634 }
635 }
636
637 #[test]
638 fn test_compare_terms_ordering() {
639 use super::compare_terms;
640
641 let number = Term::FixInteger(FixInteger { value: 42 });
643 let atom = Term::Atom(Atom::from("test"));
644 let binary = Term::Binary(eetf::Binary { bytes: b"test".to_vec() });
645
646 assert_eq!(compare_terms(&number, &atom), Ordering::Less);
648 assert_eq!(compare_terms(&atom, &number), Ordering::Greater);
649
650 assert_eq!(compare_terms(&atom, &binary), Ordering::Less);
652 assert_eq!(compare_terms(&binary, &atom), Ordering::Greater);
653
654 assert_eq!(compare_terms(&number, &binary), Ordering::Less);
656 assert_eq!(compare_terms(&binary, &number), Ordering::Greater);
657
658 let atom1 = Term::Atom(Atom::from("apple"));
660 let atom2 = Term::Atom(Atom::from("zebra"));
661 assert_eq!(compare_terms(&atom1, &atom2), Ordering::Less);
662 assert_eq!(compare_terms(&atom2, &atom1), Ordering::Greater);
663 assert_eq!(compare_terms(&atom1, &atom1), Ordering::Equal);
664 }
665
666 #[test]
667 fn test_deterministic_encoding_byte_order_verification() {
668 let mut map_data = HashMap::new();
670
671 map_data.insert(
673 Term::Binary(eetf::Binary { bytes: b"binary".to_vec() }),
674 Term::FixInteger(FixInteger { value: 3 }),
675 ); map_data.insert(Term::Atom(Atom::from("zebra")), Term::FixInteger(FixInteger { value: 2 })); map_data.insert(Term::Atom(Atom::from("apple")), Term::FixInteger(FixInteger { value: 1 })); map_data.insert(Term::FixInteger(FixInteger { value: 42 }), Term::FixInteger(FixInteger { value: 0 })); let map = Term::Map(Map { map: map_data });
681 let encoded = encode_safe_deterministic(&map);
682
683 let decoded = Term::decode(&encoded[..]).unwrap();
685 if let Term::Map(decoded_map) = decoded {
686 let mut found_keys = Vec::new();
688 for key in decoded_map.map.keys() {
689 found_keys.push(key.clone());
690 }
691
692 let mut pos = 6;
697 let mut encoded_keys = Vec::new();
698
699 for _ in 0..4 {
701 let key_start = pos;
703
704 match encoded[pos] {
706 119 => {
707 let len = encoded[pos + 1] as usize;
709 pos += 2 + len; }
711 109 => {
712 let len = u32::from_be_bytes([
714 encoded[pos + 1],
715 encoded[pos + 2],
716 encoded[pos + 3],
717 encoded[pos + 4],
718 ]) as usize;
719 pos += 5 + len; }
721 97 => {
722 pos += 2; }
725 98 => {
726 pos += 5; }
729 _ => panic!("Unexpected key type in encoded data"),
730 }
731
732 let key_end = pos;
733 encoded_keys.push(&encoded[key_start..key_end]);
734
735 match encoded[pos] {
737 97 => pos += 2, 98 => pos += 5, _ => panic!("Unexpected value type in encoded data"),
740 }
741 }
742
743 assert_eq!(encoded_keys[0][0], 97); assert_eq!(encoded_keys[0][1], 42); assert_eq!(encoded_keys[1][0], 119); assert_eq!(encoded_keys[1][1], 5); assert_eq!(&encoded_keys[1][2..7], b"apple");
757
758 assert_eq!(encoded_keys[2][0], 119); assert_eq!(encoded_keys[2][1], 5); assert_eq!(&encoded_keys[2][2..7], b"zebra");
762
763 assert_eq!(encoded_keys[3][0], 109); assert_eq!(&encoded_keys[3][1..5], &[0, 0, 0, 6]);
767 assert_eq!(&encoded_keys[3][5..11], b"binary");
768 } else {
769 panic!("Decoded term is not a map");
770 }
771 }
772
773 #[test]
774 fn test_anr_keys_correct_alphabetical_order() {
775 let mut map_data = HashMap::new();
777
778 let anr_keys = ["ip4", "pk", "pop", "port", "signature", "ts", "version", "anr_name", "anr_desc"];
780 for (i, key) in anr_keys.iter().enumerate() {
781 map_data.insert(Term::Atom(Atom::from(*key)), Term::FixInteger(FixInteger { value: i as i32 }));
782 }
783
784 let map = Term::Map(Map { map: map_data });
785 let encoded = encode_safe_deterministic(&map);
786
787 let mut pos = 6; let mut actual_key_order = Vec::new();
790
791 for _ in 0..anr_keys.len() {
792 if encoded[pos] == 119 {
794 let len = encoded[pos + 1] as usize;
796 let atom_name = std::str::from_utf8(&encoded[pos + 2..pos + 2 + len]).unwrap();
797 actual_key_order.push(atom_name.to_string());
798 pos += 2 + len; pos += 2; } else {
803 panic!("Expected atom key, found tag: {}", encoded[pos]);
804 }
805 }
806
807 let expected_order = ["anr_desc", "anr_name", "ip4", "pk", "pop", "port", "signature", "ts", "version"];
809
810 assert_eq!(
811 actual_key_order, expected_order,
812 "ANR keys should be in alphabetical order: {:?}, but got: {:?}",
813 expected_order, actual_key_order
814 );
815 }
816
817 #[test]
818 fn test_mixed_types_correct_hierarchy_order() {
819 let mut map_data = HashMap::new();
821
822 map_data.insert(Term::Binary(eetf::Binary { bytes: b"bin".to_vec() }), Term::Atom(Atom::from("last"))); map_data.insert(
825 Term::List(eetf::List { elements: vec![Term::Atom(Atom::from("item"))] }),
826 Term::Atom(Atom::from("eighth")),
827 ); map_data.insert(
829 Term::Tuple(eetf::Tuple { elements: vec![Term::Atom(Atom::from("item"))] }),
830 Term::Atom(Atom::from("sixth")),
831 ); map_data.insert(Term::Atom(Atom::from("atom")), Term::Atom(Atom::from("second"))); map_data.insert(Term::FixInteger(FixInteger { value: 123 }), Term::Atom(Atom::from("first"))); let map = Term::Map(Map { map: map_data });
836 let encoded = encode_safe_deterministic(&map);
837
838 let mut pos = 6; let mut actual_type_order = Vec::new();
841
842 for _ in 0..5 {
843 let key_tag = encoded[pos];
844 actual_type_order.push(key_tag);
845
846 match key_tag {
848 97 => pos += 2, 98 => pos += 5, 119 => {
851 let len = encoded[pos + 1] as usize;
853 pos += 2 + len;
854 }
855 104 => {
856 let _arity = encoded[pos + 1] as usize;
858 pos += 2; if encoded[pos] == 119 {
861 let len = encoded[pos + 1] as usize;
863 pos += 2 + len;
864 }
865 }
866 108 => {
867 pos += 5; if encoded[pos] == 119 {
871 let len = encoded[pos + 1] as usize;
873 pos += 2 + len;
874 }
875 pos += 1; }
877 109 => {
878 let len =
880 u32::from_be_bytes([encoded[pos + 1], encoded[pos + 2], encoded[pos + 3], encoded[pos + 4]])
881 as usize;
882 pos += 5 + len;
883 }
884 _ => panic!("Unexpected key type tag: {}", key_tag),
885 }
886
887 if encoded[pos] == 119 {
889 let len = encoded[pos + 1] as usize;
891 pos += 2 + len;
892 }
893 }
894
895 let expected_tags = [97, 119, 104, 108, 109]; assert_eq!(
899 actual_type_order, expected_tags,
900 "Key types should follow Erlang hierarchy: Numbers, Atoms, References, Ports, PIDs, Tuples, Maps, Lists, Binaries"
901 );
902 }
903
904 #[test]
905 fn test_elixir_deterministic_example_simple_map() {
906 let mut map_data = HashMap::new();
912 map_data.insert(Term::Atom(Atom::from("z")), Term::FixInteger(FixInteger { value: 1 }));
913 map_data.insert(Term::Atom(Atom::from("a")), Term::FixInteger(FixInteger { value: 2 }));
914 map_data.insert(Term::Atom(Atom::from("m")), Term::FixInteger(FixInteger { value: 3 }));
915
916 let map = Term::Map(Map { map: map_data });
917 let encoded = encode_safe_deterministic(&map);
918
919 let expected: Vec<u8> = vec![
921 131, 116, 0, 0, 0, 3, 119, 1, 97, 97, 2, 119, 1, 109, 97, 3, 119, 1, 122, 97, 1, ];
926
927 assert_eq!(
928 encoded, expected,
929 "Our encoding should match Elixir's deterministic encoding exactly.\nOur: {:?}\nExpected: {:?}",
930 encoded, expected
931 );
932 }
933
934 #[test]
935 fn test_elixir_deterministic_example_mixed_types() {
936 let mut map_data = HashMap::new();
942 map_data.insert(Term::Atom(Atom::from("atom")), Term::FixInteger(FixInteger { value: 1 }));
943 map_data.insert(
944 Term::Binary(eetf::Binary { bytes: b"string".to_vec() }),
945 Term::FixInteger(FixInteger { value: 2 }),
946 );
947 map_data.insert(Term::FixInteger(FixInteger { value: 123 }), Term::FixInteger(FixInteger { value: 3 }));
948
949 let map = Term::Map(Map { map: map_data });
950 let encoded = encode_safe_deterministic(&map);
951
952 let expected: Vec<u8> = vec![
954 131, 116, 0, 0, 0, 3, 97, 123, 97, 3, 119, 4, 97, 116, 111, 109, 97, 1, 109, 0, 0, 0, 6, 115, 116, 114, 105, 110, 103, 97, 2, ];
959
960 assert_eq!(
961 encoded, expected,
962 "Our encoding should match Elixir's deterministic encoding exactly.\nOur: {:?}\nExpected: {:?}",
963 encoded, expected
964 );
965 }
966
967 #[test]
968 fn test_decode_elixir_examples() {
969 let elixir_simple: Vec<u8> =
973 vec![131, 116, 0, 0, 0, 3, 119, 1, 97, 97, 2, 119, 1, 109, 97, 3, 119, 1, 122, 97, 1];
974
975 let decoded_simple = Term::decode(&elixir_simple[..]).unwrap();
976 if let Term::Map(map) = decoded_simple {
977 assert_eq!(map.map.len(), 3);
978 assert_eq!(map.map.get(&Term::Atom(Atom::from("a"))), Some(&Term::FixInteger(FixInteger { value: 2 })));
979 assert_eq!(map.map.get(&Term::Atom(Atom::from("m"))), Some(&Term::FixInteger(FixInteger { value: 3 })));
980 assert_eq!(map.map.get(&Term::Atom(Atom::from("z"))), Some(&Term::FixInteger(FixInteger { value: 1 })));
981 } else {
982 panic!("Failed to decode simple map");
983 }
984
985 let elixir_mixed: Vec<u8> = vec![
987 131, 116, 0, 0, 0, 3, 97, 123, 97, 3, 119, 4, 97, 116, 111, 109, 97, 1, 109, 0, 0, 0, 6, 115, 116, 114,
988 105, 110, 103, 97, 2,
989 ];
990
991 let decoded_mixed = Term::decode(&elixir_mixed[..]).unwrap();
992 if let Term::Map(map) = decoded_mixed {
993 assert_eq!(map.map.len(), 3);
994 assert_eq!(
995 map.map.get(&Term::FixInteger(FixInteger { value: 123 })),
996 Some(&Term::FixInteger(FixInteger { value: 3 }))
997 );
998 assert_eq!(map.map.get(&Term::Atom(Atom::from("atom"))), Some(&Term::FixInteger(FixInteger { value: 1 })));
999 assert_eq!(
1000 map.map.get(&Term::Binary(eetf::Binary { bytes: b"string".to_vec() })),
1001 Some(&Term::FixInteger(FixInteger { value: 2 }))
1002 );
1003 } else {
1004 panic!("Failed to decode mixed types map");
1005 }
1006 }
1007
1008 #[test]
1009 fn test_comprehensive_data_cases_1_to_10() {
1010 let mut map1 = HashMap::new();
1012 map1.insert(Term::Atom(Atom::from("m")), Term::FixInteger(FixInteger { value: 3 }));
1013 map1.insert(Term::Atom(Atom::from("a")), Term::FixInteger(FixInteger { value: 1 }));
1014 map1.insert(Term::Atom(Atom::from("z")), Term::FixInteger(FixInteger { value: 2 }));
1015 let term1 = Term::Map(Map { map: map1 });
1016 let expected1 = vec![131, 116, 0, 0, 0, 3, 119, 1, 97, 97, 1, 119, 1, 109, 97, 3, 119, 1, 122, 97, 2];
1017 assert_eq!(encode_safe_deterministic(&term1), expected1, "Test 1 failed");
1018
1019 let mut map2 = HashMap::new();
1021 map2.insert(Term::FixInteger(FixInteger { value: 123 }), Term::FixInteger(FixInteger { value: 3 }));
1022 map2.insert(Term::Float(eetf::Float { value: 45.67 }), Term::FixInteger(FixInteger { value: 4 }));
1023 map2.insert(Term::Atom(Atom::from("atom")), Term::FixInteger(FixInteger { value: 1 }));
1024 map2.insert(
1025 Term::Binary(eetf::Binary { bytes: b"string".to_vec() }),
1026 Term::FixInteger(FixInteger { value: 2 }),
1027 );
1028 let term2 = Term::Map(Map { map: map2 });
1029 let expected2 = vec![
1030 131, 116, 0, 0, 0, 4, 97, 123, 97, 3, 70, 64, 70, 213, 194, 143, 92, 40, 246, 97, 4, 119, 4, 97, 116, 111,
1031 109, 97, 1, 109, 0, 0, 0, 6, 115, 116, 114, 105, 110, 103, 97, 2,
1032 ];
1033 assert_eq!(encode_safe_deterministic(&term2), expected2, "Test 2 failed");
1034
1035 let mut inner_inner = HashMap::new();
1037 inner_inner.insert(Term::Atom(Atom::from("deep")), Term::Atom(Atom::from("value")));
1038 let mut inner = HashMap::new();
1039 inner.insert(Term::Atom(Atom::from("inner")), Term::Map(Map { map: inner_inner }));
1040 let mut map3 = HashMap::new();
1041 map3.insert(Term::Atom(Atom::from("outer")), Term::Map(Map { map: inner }));
1042 map3.insert(Term::Atom(Atom::from("top")), Term::Atom(Atom::from("level")));
1043 let term3 = Term::Map(Map { map: map3 });
1044 let expected3 = vec![
1045 131, 116, 0, 0, 0, 2, 119, 5, 111, 117, 116, 101, 114, 116, 0, 0, 0, 1, 119, 5, 105, 110, 110, 101, 114,
1046 116, 0, 0, 0, 1, 119, 4, 100, 101, 101, 112, 119, 5, 118, 97, 108, 117, 101, 119, 3, 116, 111, 112, 119, 5,
1047 108, 101, 118, 101, 108,
1048 ];
1049 assert_eq!(encode_safe_deterministic(&term3), expected3, "Test 3 failed");
1050
1051 let nested_map = {
1053 let mut m = HashMap::new();
1054 m.insert(Term::Atom(Atom::from("map")), Term::Atom(Atom::from("inside")));
1055 Term::Map(Map { map: m })
1056 };
1057 let term4 = Term::List(eetf::List {
1058 elements: vec![
1059 Term::FixInteger(FixInteger { value: 1 }),
1060 Term::Atom(Atom::from("atom")),
1061 Term::Binary(eetf::Binary { bytes: b"string".to_vec() }),
1062 Term::List(eetf::List {
1063 elements: vec![Term::Tuple(eetf::Tuple {
1064 elements: vec![Term::Atom(Atom::from("nested")), Term::Atom(Atom::from("list"))],
1065 })],
1066 }),
1067 nested_map,
1068 ],
1069 });
1070 let expected4 = vec![
1071 131, 108, 0, 0, 0, 5, 97, 1, 119, 4, 97, 116, 111, 109, 109, 0, 0, 0, 6, 115, 116, 114, 105, 110, 103, 108,
1072 0, 0, 0, 1, 104, 2, 119, 6, 110, 101, 115, 116, 101, 100, 119, 4, 108, 105, 115, 116, 106, 116, 0, 0, 0, 1,
1073 119, 3, 109, 97, 112, 119, 6, 105, 110, 115, 105, 100, 101, 106,
1074 ];
1075 assert_eq!(encode_safe_deterministic(&term4), expected4, "Test 4 failed");
1076
1077 let term5 = Term::Tuple(eetf::Tuple {
1079 elements: vec![
1080 Term::Atom(Atom::from("simple")),
1081 Term::Atom(Atom::from("tuple")),
1082 Term::FixInteger(FixInteger { value: 123 }),
1083 Term::Binary(eetf::Binary { bytes: b"mixed".to_vec() }),
1084 ],
1085 });
1086 let expected5 = vec![
1087 131, 104, 4, 119, 6, 115, 105, 109, 112, 108, 101, 119, 5, 116, 117, 112, 108, 101, 97, 123, 109, 0, 0, 0,
1088 5, 109, 105, 120, 101, 100,
1089 ];
1090 assert_eq!(encode_safe_deterministic(&term5), expected5, "Test 5 failed");
1091
1092 let mut map6 = HashMap::new();
1094 map6.insert(Term::Binary(eetf::Binary { bytes: b"apple".to_vec() }), Term::Atom(Atom::from("a")));
1095 map6.insert(Term::Binary(eetf::Binary { bytes: b"monkey".to_vec() }), Term::Atom(Atom::from("m")));
1096 map6.insert(Term::Binary(eetf::Binary { bytes: b"zebra".to_vec() }), Term::Atom(Atom::from("z")));
1097 let term6 = Term::Map(Map { map: map6 });
1098 let expected6 = vec![
1099 131, 116, 0, 0, 0, 3, 109, 0, 0, 0, 5, 97, 112, 112, 108, 101, 119, 1, 97, 109, 0, 0, 0, 6, 109, 111, 110,
1100 107, 101, 121, 119, 1, 109, 109, 0, 0, 0, 5, 122, 101, 98, 114, 97, 119, 1, 122,
1101 ];
1102 assert_eq!(encode_safe_deterministic(&term6), expected6, "Test 6 failed");
1103
1104 let mut map7 = HashMap::new();
1106 map7.insert(Term::FixInteger(FixInteger { value: -5 }), Term::Atom(Atom::from("negative")));
1107 map7.insert(Term::FixInteger(FixInteger { value: 1 }), Term::Atom(Atom::from("one")));
1108 map7.insert(Term::FixInteger(FixInteger { value: 999 }), Term::Atom(Atom::from("big")));
1109 map7.insert(Term::Float(eetf::Float { value: 2.5 }), Term::Atom(Atom::from("two_half")));
1110 let term7 = Term::Map(Map { map: map7 });
1111 let expected7 = vec![
1112 131, 116, 0, 0, 0, 4, 98, 255, 255, 255, 251, 119, 8, 110, 101, 103, 97, 116, 105, 118, 101, 97, 1, 119, 3,
1113 111, 110, 101, 98, 0, 0, 3, 231, 119, 3, 98, 105, 103, 70, 64, 4, 0, 0, 0, 0, 0, 0, 119, 8, 116, 119, 111,
1114 95, 104, 97, 108, 102,
1115 ];
1116 assert_eq!(encode_safe_deterministic(&term7), expected7, "Test 7 failed");
1117
1118 let mut config_map = HashMap::new();
1120 config_map.insert(Term::Atom(Atom::from("debug")), Term::Atom(Atom::from("true")));
1121 config_map.insert(Term::Atom(Atom::from("timeout")), Term::FixInteger(FixInteger { value: 5000 }));
1122
1123 let mut user1 = HashMap::new();
1124 user1.insert(Term::Atom(Atom::from("id")), Term::FixInteger(FixInteger { value: 1 }));
1125 user1.insert(Term::Atom(Atom::from("name")), Term::Binary(eetf::Binary { bytes: b"Alice".to_vec() }));
1126 user1.insert(
1127 Term::Atom(Atom::from("roles")),
1128 Term::List(eetf::List { elements: vec![Term::Atom(Atom::from("admin")), Term::Atom(Atom::from("user"))] }),
1129 );
1130
1131 let mut user2 = HashMap::new();
1132 user2.insert(Term::Atom(Atom::from("id")), Term::FixInteger(FixInteger { value: 2 }));
1133 user2.insert(Term::Atom(Atom::from("name")), Term::Binary(eetf::Binary { bytes: b"Bob".to_vec() }));
1134 user2.insert(
1135 Term::Atom(Atom::from("roles")),
1136 Term::List(eetf::List { elements: vec![Term::Atom(Atom::from("user"))] }),
1137 );
1138
1139 let mut map8 = HashMap::new();
1140 map8.insert(Term::Atom(Atom::from("config")), Term::Map(Map { map: config_map }));
1141 map8.insert(
1142 Term::Atom(Atom::from("users")),
1143 Term::List(eetf::List { elements: vec![Term::Map(Map { map: user1 }), Term::Map(Map { map: user2 })] }),
1144 );
1145 let term8 = Term::Map(Map { map: map8 });
1146 let expected8 = vec![
1147 131, 116, 0, 0, 0, 2, 119, 6, 99, 111, 110, 102, 105, 103, 116, 0, 0, 0, 2, 119, 5, 100, 101, 98, 117, 103,
1148 119, 4, 116, 114, 117, 101, 119, 7, 116, 105, 109, 101, 111, 117, 116, 98, 0, 0, 19, 136, 119, 5, 117, 115,
1149 101, 114, 115, 108, 0, 0, 0, 2, 116, 0, 0, 0, 3, 119, 2, 105, 100, 97, 1, 119, 4, 110, 97, 109, 101, 109,
1150 0, 0, 0, 5, 65, 108, 105, 99, 101, 119, 5, 114, 111, 108, 101, 115, 108, 0, 0, 0, 2, 119, 5, 97, 100, 109,
1151 105, 110, 119, 4, 117, 115, 101, 114, 106, 116, 0, 0, 0, 3, 119, 2, 105, 100, 97, 2, 119, 4, 110, 97, 109,
1152 101, 109, 0, 0, 0, 3, 66, 111, 98, 119, 5, 114, 111, 108, 101, 115, 108, 0, 0, 0, 1, 119, 4, 117, 115, 101,
1153 114, 106, 106,
1154 ];
1155 assert_eq!(encode_safe_deterministic(&term8), expected8, "Test 8 failed");
1156
1157 let mut deepest = HashMap::new();
1159 deepest.insert(Term::FixInteger(FixInteger { value: 4 }), Term::Atom(Atom::from("very_deep")));
1160 let mut deep_map = HashMap::new();
1161 deep_map.insert(Term::Atom(Atom::from("deep")), Term::Map(Map { map: deepest }));
1162 let mut nested_map = HashMap::new();
1163 nested_map.insert(Term::Binary(eetf::Binary { bytes: b"nested".to_vec() }), Term::Map(Map { map: deep_map }));
1164 let mut map9 = HashMap::new();
1165 map9.insert(Term::FixInteger(FixInteger { value: 1 }), Term::Map(Map { map: nested_map }));
1166 map9.insert(Term::Atom(Atom::from("top")), Term::Binary(eetf::Binary { bytes: b"level".to_vec() }));
1167 let term9 = Term::Map(Map { map: map9 });
1168 let expected9 = vec![
1169 131, 116, 0, 0, 0, 2, 97, 1, 116, 0, 0, 0, 1, 109, 0, 0, 0, 6, 110, 101, 115, 116, 101, 100, 116, 0, 0, 0,
1170 1, 119, 4, 100, 101, 101, 112, 116, 0, 0, 0, 1, 97, 4, 119, 9, 118, 101, 114, 121, 95, 100, 101, 101, 112,
1171 119, 3, 116, 111, 112, 109, 0, 0, 0, 5, 108, 101, 118, 101, 108,
1172 ];
1173 assert_eq!(encode_safe_deterministic(&term9), expected9, "Test 9 failed");
1174
1175 let term10 = Term::List(eetf::List {
1177 elements: vec![
1178 Term::Tuple(eetf::Tuple {
1179 elements: vec![
1180 Term::Atom(Atom::from("name")),
1181 Term::Binary(eetf::Binary { bytes: b"John".to_vec() }),
1182 ],
1183 }),
1184 Term::Tuple(eetf::Tuple {
1185 elements: vec![Term::Atom(Atom::from("age")), Term::FixInteger(FixInteger { value: 30 })],
1186 }),
1187 Term::Tuple(eetf::Tuple {
1188 elements: vec![
1189 Term::Atom(Atom::from("city")),
1190 Term::Binary(eetf::Binary { bytes: b"NYC".to_vec() }),
1191 ],
1192 }),
1193 Term::Tuple(eetf::Tuple {
1194 elements: vec![Term::FixInteger(FixInteger { value: 1 }), Term::Atom(Atom::from("number_key"))],
1195 }),
1196 ],
1197 });
1198 let expected10 = vec![
1199 131, 108, 0, 0, 0, 4, 104, 2, 119, 4, 110, 97, 109, 101, 109, 0, 0, 0, 4, 74, 111, 104, 110, 104, 2, 119,
1200 3, 97, 103, 101, 97, 30, 104, 2, 119, 4, 99, 105, 116, 121, 109, 0, 0, 0, 3, 78, 89, 67, 104, 2, 97, 1,
1201 119, 10, 110, 117, 109, 98, 101, 114, 95, 107, 101, 121, 106,
1202 ];
1203 assert_eq!(encode_safe_deterministic(&term10), expected10, "Test 10 failed");
1204 }
1205
1206 #[test]
1207 fn test_comprehensive_data_cases_special_selection() {
1208 let mut map23 = HashMap::new();
1210 map23.insert(Term::Atom(Atom::from("port")), Term::FixInteger(FixInteger { value: 36969 }));
1211 map23.insert(Term::Atom(Atom::from("version")), Term::Binary(eetf::Binary { bytes: b"1.1.5".to_vec() }));
1212 map23.insert(Term::Atom(Atom::from("signature")), Term::Binary(eetf::Binary { bytes: vec![13, 14, 15, 16] }));
1213 map23.insert(Term::Atom(Atom::from("pop")), Term::Binary(eetf::Binary { bytes: vec![9, 10, 11, 12] }));
1214 map23.insert(Term::Atom(Atom::from("ip4")), Term::Binary(eetf::Binary { bytes: b"192.168.1.1".to_vec() }));
1215 map23.insert(Term::Atom(Atom::from("ts")), Term::FixInteger(FixInteger { value: 1640995200 }));
1216 map23.insert(Term::Atom(Atom::from("pk")), Term::Binary(eetf::Binary { bytes: vec![1, 2, 3, 4, 5, 6, 7, 8] }));
1217 map23.insert(Term::Atom(Atom::from("anr_name")), Term::Binary(eetf::Binary { bytes: b"test_node".to_vec() }));
1218 map23.insert(
1219 Term::Atom(Atom::from("anr_desc")),
1220 Term::Binary(eetf::Binary { bytes: b"Test description".to_vec() }),
1221 );
1222 let term23 = Term::Map(Map { map: map23 });
1223 let expected23 = vec![
1224 131, 116, 0, 0, 0, 9, 119, 8, 97, 110, 114, 95, 100, 101, 115, 99, 109, 0, 0, 0, 16, 84, 101, 115, 116, 32,
1225 100, 101, 115, 99, 114, 105, 112, 116, 105, 111, 110, 119, 8, 97, 110, 114, 95, 110, 97, 109, 101, 109, 0,
1226 0, 0, 9, 116, 101, 115, 116, 95, 110, 111, 100, 101, 119, 3, 105, 112, 52, 109, 0, 0, 0, 11, 49, 57, 50,
1227 46, 49, 54, 56, 46, 49, 46, 49, 119, 2, 112, 107, 109, 0, 0, 0, 8, 1, 2, 3, 4, 5, 6, 7, 8, 119, 3, 112,
1228 111, 112, 109, 0, 0, 0, 4, 9, 10, 11, 12, 119, 4, 112, 111, 114, 116, 98, 0, 0, 144, 105, 119, 9, 115, 105,
1229 103, 110, 97, 116, 117, 114, 101, 109, 0, 0, 0, 4, 13, 14, 15, 16, 119, 2, 116, 115, 98, 97, 207, 153, 128,
1230 119, 7, 118, 101, 114, 115, 105, 111, 110, 109, 0, 0, 0, 5, 49, 46, 49, 46, 53,
1231 ];
1232 assert_eq!(encode_safe_deterministic(&term23), expected23, "Test 23 (ANR) failed");
1233
1234 let mut map11 = HashMap::new();
1236 map11.insert(Term::Atom(Atom::from("simple")), Term::Atom(Atom::from("value3")));
1237 map11.insert(
1238 Term::Tuple(eetf::Tuple {
1239 elements: vec![Term::Atom(Atom::from("another")), Term::Atom(Atom::from("compound"))],
1240 }),
1241 Term::Atom(Atom::from("value2")),
1242 );
1243 map11.insert(
1244 Term::Tuple(eetf::Tuple {
1245 elements: vec![Term::Atom(Atom::from("compound")), Term::Atom(Atom::from("key"))],
1246 }),
1247 Term::Atom(Atom::from("value1")),
1248 );
1249 let term11 = Term::Map(Map { map: map11 });
1250 let expected11 = vec![
1251 131, 116, 0, 0, 0, 3, 119, 6, 115, 105, 109, 112, 108, 101, 119, 6, 118, 97, 108, 117, 101, 51, 104, 2,
1252 119, 7, 97, 110, 111, 116, 104, 101, 114, 119, 8, 99, 111, 109, 112, 111, 117, 110, 100, 119, 6, 118, 97,
1253 108, 117, 101, 50, 104, 2, 119, 8, 99, 111, 109, 112, 111, 117, 110, 100, 119, 3, 107, 101, 121, 119, 6,
1254 118, 97, 108, 117, 101, 49,
1255 ];
1256 assert_eq!(encode_safe_deterministic(&term11), expected11, "Test 11 failed");
1257
1258 let term13 = Term::List(eetf::List {
1260 elements: vec![
1261 Term::Atom(Atom::from("zebra")),
1262 Term::Atom(Atom::from("alpha")),
1263 Term::Atom(Atom::from("beta")),
1264 Term::Atom(Atom::from("gamma")),
1265 Term::Atom(Atom::from("omega")),
1266 ],
1267 });
1268 let expected13 = vec![
1269 131, 108, 0, 0, 0, 5, 119, 5, 122, 101, 98, 114, 97, 119, 5, 97, 108, 112, 104, 97, 119, 4, 98, 101, 116,
1270 97, 119, 5, 103, 97, 109, 109, 97, 119, 5, 111, 109, 101, 103, 97, 106,
1271 ];
1272 assert_eq!(encode_safe_deterministic(&term13), expected13, "Test 13 failed");
1273
1274 let mut map21 = HashMap::new();
1276 map21.insert(Term::FixInteger(FixInteger { value: 1 }), Term::Atom(Atom::from("one")));
1277 map21.insert(Term::FixInteger(FixInteger { value: 500 }), Term::Atom(Atom::from("five_hundred")));
1278 map21.insert(Term::FixInteger(FixInteger { value: 99999 }), Term::Atom(Atom::from("almost_hundred_k")));
1279 map21.insert(Term::FixInteger(FixInteger { value: 1000000 }), Term::Atom(Atom::from("million")));
1280 let term21 = Term::Map(Map { map: map21 });
1281 let expected21 = vec![
1282 131, 116, 0, 0, 0, 4, 97, 1, 119, 3, 111, 110, 101, 98, 0, 0, 1, 244, 119, 12, 102, 105, 118, 101, 95, 104,
1283 117, 110, 100, 114, 101, 100, 98, 0, 1, 134, 159, 119, 16, 97, 108, 109, 111, 115, 116, 95, 104, 117, 110,
1284 100, 114, 101, 100, 95, 107, 98, 0, 15, 66, 64, 119, 7, 109, 105, 108, 108, 105, 111, 110,
1285 ];
1286 assert_eq!(encode_safe_deterministic(&term21), expected21, "Test 21 failed");
1287
1288 let mut map29 = HashMap::new();
1290 map29.insert(Term::FixInteger(FixInteger { value: -1000 }), Term::Atom(Atom::from("neg_thousand")));
1291 map29.insert(Term::FixInteger(FixInteger { value: -1 }), Term::Atom(Atom::from("neg_one")));
1292 map29.insert(Term::FixInteger(FixInteger { value: 0 }), Term::Atom(Atom::from("zero")));
1293 map29.insert(Term::Float(eetf::Float { value: 0.0 }), Term::Atom(Atom::from("float_zero")));
1294 let term29 = Term::Map(Map { map: map29 });
1295 let expected29 = vec![
1296 131, 116, 0, 0, 0, 4, 98, 255, 255, 252, 24, 119, 12, 110, 101, 103, 95, 116, 104, 111, 117, 115, 97, 110,
1297 100, 98, 255, 255, 255, 255, 119, 7, 110, 101, 103, 95, 111, 110, 101, 97, 0, 119, 4, 122, 101, 114, 111,
1298 70, 0, 0, 0, 0, 0, 0, 0, 0, 119, 10, 102, 108, 111, 97, 116, 95, 122, 101, 114, 111,
1299 ];
1300 assert_eq!(encode_safe_deterministic(&term29), expected29, "Test 29 failed");
1301 }
1302
1303 #[test]
1304 fn test_comprehensive_data_byte_list_cases() {
1305 let mut map14 = HashMap::new();
1307 map14.insert(Term::Atom(Atom::from("binary")), Term::Binary(eetf::Binary { bytes: vec![1, 2, 3] }));
1308 map14.insert(Term::Atom(Atom::from("list")), Term::ByteList(eetf::ByteList { bytes: vec![1, 2, 3] }));
1309 map14.insert(Term::Atom(Atom::from("map")), {
1310 let mut inner = HashMap::new();
1311 inner.insert(Term::Atom(Atom::from("a")), Term::FixInteger(FixInteger { value: 1 }));
1312 inner.insert(Term::Atom(Atom::from("b")), Term::FixInteger(FixInteger { value: 2 }));
1313 Term::Map(Map { map: inner })
1314 });
1315 map14.insert(
1316 Term::Atom(Atom::from("tuple")),
1317 Term::Tuple(eetf::Tuple {
1318 elements: vec![
1319 Term::FixInteger(FixInteger { value: 1 }),
1320 Term::FixInteger(FixInteger { value: 2 }),
1321 Term::FixInteger(FixInteger { value: 3 }),
1322 ],
1323 }),
1324 );
1325 let term14 = Term::Map(Map { map: map14 });
1326 let expected14 = vec![
1327 131, 116, 0, 0, 0, 4, 119, 6, 98, 105, 110, 97, 114, 121, 109, 0, 0, 0, 3, 1, 2, 3, 119, 4, 108, 105, 115,
1328 116, 107, 0, 3, 1, 2, 3, 119, 3, 109, 97, 112, 116, 0, 0, 0, 2, 119, 1, 97, 97, 1, 119, 1, 98, 97, 2, 119,
1329 5, 116, 117, 112, 108, 101, 104, 3, 97, 1, 97, 2, 97, 3,
1330 ];
1331 assert_eq!(encode_safe_deterministic(&term14), expected14, "Test 14 failed");
1332
1333 let mut map34 = HashMap::new();
1335 map34.insert(Term::Atom(Atom::from("string")), Term::Binary(eetf::Binary { bytes: b"hello".to_vec() }));
1336 map34.insert(Term::Atom(Atom::from("charlist")), Term::ByteList(eetf::ByteList { bytes: b"hello".to_vec() }));
1337 map34.insert(Term::Atom(Atom::from("mixed_list")), Term::ByteList(eetf::ByteList { bytes: b"Hello".to_vec() }));
1338 let term34 = Term::Map(Map { map: map34 });
1339 let expected34 = vec![
1340 131, 116, 0, 0, 0, 3, 119, 8, 99, 104, 97, 114, 108, 105, 115, 116, 107, 0, 5, 104, 101, 108, 108, 111,
1341 119, 10, 109, 105, 120, 101, 100, 95, 108, 105, 115, 116, 107, 0, 5, 72, 101, 108, 108, 111, 119, 6, 115,
1342 116, 114, 105, 110, 103, 109, 0, 0, 0, 5, 104, 101, 108, 108, 111,
1343 ];
1344 assert_eq!(encode_safe_deterministic(&term34), expected34, "Test 34 failed");
1345 }
1346
1347 #[test]
1348 fn test_large_integers_elixir_compatibility() {
1349 use eetf::BigInteger;
1350
1351 let very_small = Term::BigInteger(BigInteger::from(214u64));
1352 let encoded_very_small = encode_safe(&very_small);
1353 println!("{:?}", encoded_very_small);
1354
1355 let small = Term::BigInteger(BigInteger::from(2147483648u64));
1358 let encoded_small = encode_safe(&small);
1359 let expected_small = vec![131, 110, 4, 0, 0, 0, 0, 128];
1360 assert_eq!(
1361 encoded_small, expected_small,
1362 "Encoding mismatch for 2147483648\nOur: {:?}\nExpected: {:?}",
1363 encoded_small, expected_small
1364 );
1365
1366 let edge = Term::BigInteger(BigInteger::from(4294967296u64));
1369 let encoded_edge = encode_safe(&edge);
1370 let expected_edge = vec![131, 110, 5, 0, 0, 0, 0, 0, 1];
1371 assert_eq!(
1372 encoded_edge, expected_edge,
1373 "Encoding mismatch for 4294967296\nOur: {:?}\nExpected: {:?}",
1374 encoded_edge, expected_edge
1375 );
1376
1377 let over = Term::BigInteger(BigInteger::from(8589934592u64));
1380 let encoded_over = encode_safe(&over);
1381 let expected_over = vec![131, 110, 5, 0, 0, 0, 0, 0, 2];
1382 assert_eq!(
1383 encoded_over, expected_over,
1384 "Encoding mismatch for 8589934592\nOur: {:?}\nExpected: {:?}",
1385 encoded_over, expected_over
1386 );
1387
1388 let decoded_small = Term::decode(&encoded_small[..]).unwrap();
1390 if let Term::BigInteger(val) = decoded_small {
1391 assert_eq!(val.value, BigInteger::from(2147483648u64).value);
1392 } else {
1393 panic!("Failed to decode 2147483648 as BigInteger");
1394 }
1395
1396 let decoded_edge = Term::decode(&encoded_edge[..]).unwrap();
1397 if let Term::BigInteger(val) = decoded_edge {
1398 assert_eq!(val.value, BigInteger::from(4294967296u64).value);
1399 } else {
1400 panic!("Failed to decode 4294967296 as BigInteger");
1401 }
1402
1403 let decoded_over = Term::decode(&encoded_over[..]).unwrap();
1404 if let Term::BigInteger(val) = decoded_over {
1405 assert_eq!(val.value, BigInteger::from(8589934592u64).value);
1406 } else {
1407 panic!("Failed to decode 8589934592 as BigInteger");
1408 }
1409
1410 let mut map = HashMap::new();
1414 map.insert(Term::Atom(Atom::from("a")), Term::BigInteger(BigInteger::from(8589934592u64)));
1415 map.insert(
1416 Term::Atom(Atom::from("b")),
1417 Term::Binary(eetf::Binary { bytes: vec![131, 110, 5, 0, 0, 0, 0, 0, 2] }),
1418 );
1419 let map_term = Term::Map(Map { map });
1420 let encoded_map = encode_safe_deterministic(&map_term);
1421 let expected_map = vec![
1422 131, 116, 0, 0, 0, 2, 119, 1, 97, 110, 5, 0, 0, 0, 0, 0, 2, 119, 1, 98, 109, 0, 0, 0, 9, 131, 110, 5, 0, 0, 0, 0, 0, 2, ];
1426 assert_eq!(
1427 encoded_map, expected_map,
1428 "Encoding mismatch for map with large integer and binary\nOur: {:?}\nExpected: {:?}",
1429 encoded_map, expected_map
1430 );
1431
1432 let decoded_map = Term::decode(&encoded_map[..]).unwrap();
1434 if let Term::Map(decoded) = decoded_map {
1435 assert_eq!(decoded.map.len(), 2);
1436
1437 if let Some(Term::BigInteger(val)) = decoded.map.get(&Term::Atom(Atom::from("a"))) {
1439 assert_eq!(val.value, BigInteger::from(8589934592u64).value);
1440 } else {
1441 panic!("Failed to find or decode key 'a' as BigInteger");
1442 }
1443
1444 if let Some(Term::Binary(bin)) = decoded.map.get(&Term::Atom(Atom::from("b"))) {
1446 assert_eq!(bin.bytes, vec![131, 110, 5, 0, 0, 0, 0, 0, 2]);
1447 } else {
1448 panic!("Failed to find or decode key 'b' as Binary");
1449 }
1450 } else {
1451 panic!("Failed to decode map");
1452 }
1453 }
1454}