1use crate::Term;
2use keylist::Keylist;
3use nom::error::Error;
4use nom::Err as NomErr;
5use num_bigint::BigInt;
6use ordered_float::OrderedFloat;
7use std::collections::HashMap;
8use strum::EnumDiscriminants;
9
10#[derive(Debug, Clone, Hash, PartialEq, EnumDiscriminants)]
11#[strum_discriminants(name(RawTermType))]
12#[cfg_attr(feature = "serde_impl", derive(Serialize, Deserialize))]
13pub enum RawTerm {
15 SmallInt(u8),
17 Int(i32),
18 SmallTuple(Vec<RawTerm>),
22 LargeTuple(Vec<RawTerm>),
23 Map(Vec<(RawTerm, RawTerm)>),
24 Nil,
25 String(Vec<u8>),
26 List(Vec<RawTerm>),
27 Improper(Box<RawTerm>),
28 Binary(Vec<u8>),
29 BitBinary {
30 binary: Vec<u8>,
31 bit: u8,
32 bits: u8,
33 },
34 SmallBigInt(BigInt),
35 LargeBigInt(BigInt),
36 Pid {
37 node: Box<RawTerm>,
38 id: u32,
39 serial: u32,
40 creation: u8,
41 },
42 NewPid {
43 node: Box<RawTerm>,
44 id: u32,
45 serial: u32,
46 creation: u32,
47 },
48 Port {
49 node: Box<RawTerm>,
50 id: u32,
51 creation: u8,
52 },
53 NewPort {
54 node: Box<RawTerm>,
55 id: u32,
56 creation: u32,
57 },
58 Ref {
59 node: Box<RawTerm>,
60 id: Vec<u32>,
61 creation: u8,
62 },
63 NewerRef {
64 node: Box<RawTerm>,
65 id: Vec<u32>,
66 creation: u32,
67 },
68 Function {
69 size: u32,
70 arity: u8,
71 uniq: [u8; 16],
72 index: u32,
73 module: Box<RawTerm>,
74 old_index: Box<RawTerm>,
75 old_uniq: Box<RawTerm>,
76 pid: Box<RawTerm>,
77 free_var: Vec<RawTerm>,
78 },
79 Float(OrderedFloat<f64>),
84 Atom(String),
85 SmallAtom(String),
86 AtomDeprecated(String),
88 SmallAtomDeprecated(String),
89}
90
91impl RawTerm {
92 pub fn from_bytes(input: &[u8]) -> Result<RawTerm, NomErr<Error<&[u8]>>> {
93 crate::from_bytes(input)
94 }
95
96 pub fn to_bytes(self) -> Vec<u8> {
97 crate::to_bytes(self)
98 }
99
100 #[cfg(feature = "zlib")]
101 pub fn to_gzip_bytes(self, level: flate2::Compression) -> std::io::Result<Vec<u8>> {
102 crate::to_gzip_bytes(self, level)
103 }
104
105 pub fn as_type(&self) -> RawTermType {
106 RawTermType::from(self)
107 }
108
109 pub fn as_general_type(&self) -> RawTermGeneralType {
110 RawTermGeneralType::from(self.as_type())
111 }
112
113 pub fn is_atom(&self) -> bool {
114 use RawTerm::*;
115 matches!(
116 self,
117 Atom(_) | AtomDeprecated(_) | SmallAtom(_) | SmallAtomDeprecated(_)
118 )
119 }
120
121 pub fn is_string(&self) -> bool {
122 use RawTerm::*;
123 matches!(self, Binary(_) | String(_))
124 }
125
126 pub fn is_string_like(&self) -> bool {
128 self.is_string() | self.is_atom()
129 }
130
131 pub fn is_integer(&self) -> bool {
132 use RawTerm::*;
133 matches!(self, SmallInt(_) | Int(_))
134 }
135
136 pub fn is_atom_pair(&self) -> bool {
137 use RawTerm::*;
138 match self {
139 SmallTuple(x) if x.len() == 2 => x[0].is_atom(),
140 _ => false,
141 }
142 }
143
144 pub fn is_string_map(&self) -> bool {
145 use RawTerm::*;
146 match self {
147 Map(x) => x.iter().all(|(a, _)| a.is_string_like()),
148 _ => false,
149 }
150 }
151
152 pub fn is_list(&self) -> bool {
153 use RawTerm::*;
154 matches!(self, List(_))
155 }
156
157 pub fn as_atom(self) -> Option<String> {
158 use RawTerm::*;
159 match self {
160 Atom(x) | AtomDeprecated(x) | SmallAtom(x) | SmallAtomDeprecated(x) => Some(x),
161 _ => None,
162 }
163 }
164
165 pub fn as_string(self) -> Option<String> {
166 match self {
167 RawTerm::Binary(x) | RawTerm::String(x) => {
168 Some(String::from_utf8(x).expect("binary not utf-8"))
169 }
170 _ => None,
171 }
172 }
173
174 pub fn as_string_like(self) -> Option<String> {
175 if self.is_string() {
176 self.as_string()
177 } else if self.is_atom() {
178 self.as_atom()
179 } else {
180 None
181 }
182 }
183
184 pub fn as_atom_pair(self) -> Option<(String, RawTerm)> {
185 use RawTerm::*;
186 match self {
187 SmallTuple(mut x) | LargeTuple(mut x) if x.len() == 2 => {
188 let b = x.pop().expect("length is two");
189 if let Some(a) = x.pop().expect("length is two").as_atom() {
190 return Some((a, b));
191 }
192 }
193 _ => (),
194 }
195 None
196 }
197}
198
199impl From<Term> for RawTerm {
200 fn from(term: Term) -> RawTerm {
201 match term {
202 Term::Byte(x) => RawTerm::SmallInt(x),
203 Term::Int(x) => RawTerm::Int(x),
204 Term::Float(x) => RawTerm::Float(x),
205 Term::String(x) => string_to_raw_term(x),
206 Term::Atom(x) => atom_to_raw_term(x),
207 Term::Bytes(x) => RawTerm::Binary(x),
208 Term::Bool(x) => RawTerm::SmallAtom(x.to_string()),
209 Term::Nil => RawTerm::SmallAtom("nil".to_string()),
210 Term::BigInt(x) => big_int_to_raw_term(x),
211 Term::Charlist(x) => RawTerm::String(x),
212 Term::Keyword(x) => keyword_to_raw_term(x),
213 Term::List(x) => list_to_raw_term(x),
214 Term::Tuple(x) => tuple_to_raw_term(x),
215 Term::Map(x) => map_arbitrary_to_raw_term(x),
216 Term::Other(x) => x,
217 }
218 }
219}
220
221fn string_to_raw_term(string: String) -> RawTerm {
222 RawTerm::Binary(string.as_bytes().to_vec())
223}
224
225fn keyword_to_raw_term(keyword: Keylist<String, Term>) -> RawTerm {
226 let tmp: Vec<RawTerm> = keyword
227 .into_iter()
228 .map(|(a, b)| RawTerm::SmallTuple(vec![string_to_raw_term(a), RawTerm::from(b)]))
229 .collect();
230 RawTerm::List(tmp)
231}
232
233fn map_arbitrary_to_raw_term(map: HashMap<Term, Term>) -> RawTerm {
234 let tmp = map
235 .into_iter()
236 .map(|(k, v)| (RawTerm::from(k), RawTerm::from(v)))
237 .collect();
238 RawTerm::Map(tmp)
239}
240
241fn list_to_raw_term(list: Vec<Term>) -> RawTerm {
242 if list.is_empty() {
243 RawTerm::Nil
244 } else {
245 RawTerm::List(list.into_iter().map(RawTerm::from).collect())
246 }
247}
248
249fn tuple_to_raw_term(tuple: Vec<Term>) -> RawTerm {
250 let len = tuple.len();
251 let x = tuple.into_iter().map(RawTerm::from).collect();
252 if len < 16 {
253 RawTerm::SmallTuple(x)
254 } else {
255 RawTerm::LargeTuple(x)
256 }
257}
258
259fn big_int_to_raw_term(input: BigInt) -> RawTerm {
260 if input.bits() < (255 * 8) {
261 RawTerm::SmallBigInt(input)
262 } else {
263 RawTerm::LargeBigInt(input)
264 }
265}
266
267fn atom_to_raw_term(input: String) -> RawTerm {
268 if input.len() < 256 {
269 RawTerm::SmallAtom(input)
270 } else {
271 RawTerm::Atom(input)
272 }
273}
274
275#[derive(Debug, PartialEq, PartialOrd)]
276pub enum RawTermGeneralType {
278 Improper,
280 Number,
281 Atom,
282 Reference,
283 Fun,
284 Port,
285 Pid,
286 Tuple,
287 Map,
288 Nil,
289 List,
290 BitString,
291}
292
293impl From<RawTermType> for RawTermGeneralType {
294 fn from(item: RawTermType) -> RawTermGeneralType {
295 RawTermGeneralType::from(&item)
296 }
297}
298
299impl From<&RawTermType> for RawTermGeneralType {
300 fn from(item: &RawTermType) -> RawTermGeneralType {
301 use RawTermType::*;
302 match item {
303 SmallInt => RawTermGeneralType::Number,
304 Int => RawTermGeneralType::Number,
305 SmallTuple => RawTermGeneralType::Tuple,
306 LargeTuple => RawTermGeneralType::Tuple,
307 Map => RawTermGeneralType::Map,
308 Nil => RawTermGeneralType::Nil,
309 String => RawTermGeneralType::BitString,
310 List => RawTermGeneralType::List,
311 Improper => RawTermGeneralType::Improper,
312 Binary => RawTermGeneralType::BitString,
313 BitBinary => RawTermGeneralType::BitString,
314 SmallBigInt => RawTermGeneralType::Number,
315 LargeBigInt => RawTermGeneralType::Number,
316 Pid => RawTermGeneralType::Pid,
317 NewPid => RawTermGeneralType::Pid,
318 Port => RawTermGeneralType::Port,
319 NewPort => RawTermGeneralType::Port,
320 Ref => RawTermGeneralType::Reference,
321 NewerRef => RawTermGeneralType::Reference,
322 Function => RawTermGeneralType::Fun,
323 Float => RawTermGeneralType::Number,
324 Atom => RawTermGeneralType::Atom,
325 SmallAtom => RawTermGeneralType::Atom,
326 AtomDeprecated => RawTermGeneralType::Atom,
327 SmallAtomDeprecated => RawTermGeneralType::Atom,
328 }
329 }
330}
331
332#[cfg(test)]
333mod from_term_tests {
334 use crate::{from_bytes, read_binary, RawTerm};
335 use num_bigint::{BigInt, BigUint};
336
337 #[test]
338 fn small_int() {
339 let input = read_binary("bins/small_int.bin").unwrap();
340 let out = from_bytes(&input).unwrap();
341
342 assert_eq!(RawTerm::SmallInt(2), out);
343 }
344
345 #[test]
346 fn small_negative_int() {
347 let input = read_binary("bins/small_negative_int.bin").unwrap();
348 let out = from_bytes(&input).unwrap();
349
350 assert_eq!(RawTerm::Int(-2), out);
351 }
352
353 #[test]
354 fn int() {
355 let input = read_binary("bins/int.bin").unwrap();
356 let out = from_bytes(&input).unwrap();
357
358 assert_eq!(RawTerm::Int(1234578), out);
359 }
360
361 #[test]
362 fn negative_int() {
363 let input = read_binary("bins/negative_int.bin").unwrap();
364 let out = from_bytes(&input).unwrap();
365
366 assert_eq!(RawTerm::Int(-1234578), out);
367 }
368
369 #[test]
370 fn nil() {
371 let input = read_binary("bins/nil.bin").unwrap();
372 let out = from_bytes(&input).unwrap();
373
374 assert_eq!(RawTerm::AtomDeprecated("nil".to_string()), out);
375 }
376
377 #[test]
378 fn false_test() {
379 let input = read_binary("bins/false.bin").unwrap();
380 let out = from_bytes(&input).unwrap();
381
382 assert_eq!(RawTerm::AtomDeprecated("false".to_string()), out);
383 }
384
385 #[test]
386 fn true_test() {
387 let input = read_binary("bins/true.bin").unwrap();
388 let out = from_bytes(&input).unwrap();
389
390 assert_eq!(RawTerm::AtomDeprecated("true".to_string()), out);
391 }
392
393 #[test]
394 fn odd_atom() {
395 let input = read_binary("bins/odd_atom.bin").unwrap();
396 let out = from_bytes(&input).unwrap();
397
398 assert_eq!(RawTerm::SmallAtom("oddţ".to_string()), out);
399 }
400
401 #[test]
402 fn module_name() {
403 let input = read_binary("bins/module_name.bin").unwrap();
404 let out = from_bytes(&input).unwrap();
405
406 assert_eq!(
407 RawTerm::AtomDeprecated("Elixir.TermGenerator".to_string()),
408 out
409 );
410 }
411
412 #[test]
413 fn elixir_struct() {
414 let input = read_binary("bins/struct.bin").unwrap();
415 let out = from_bytes(&input).unwrap();
416
417 let expected = RawTerm::Map(
418 vec![
419 (
420 RawTerm::AtomDeprecated("__struct__".to_string()),
421 RawTerm::AtomDeprecated("Elixir.TestStruct".to_string()),
422 ),
423 (
424 RawTerm::AtomDeprecated("a".to_string()),
425 RawTerm::AtomDeprecated("nil".to_string()),
426 ),
427 (RawTerm::AtomDeprecated("b".to_string()), RawTerm::Int(1234)),
428 ]
429 .into_iter()
430 .collect(),
431 );
432
433 assert_eq!(expected, out);
434 }
435
436 #[test]
437 fn small_string() {
438 let input = read_binary("bins/small_string.bin").unwrap();
439 let out = from_bytes(&input).unwrap();
440
441 assert_eq!(RawTerm::Binary(b"just some text".to_vec()), out);
442 }
443
444 #[test]
445 fn binary() {
446 let input = read_binary("bins/binary.bin").unwrap();
447 let out = from_bytes(&input).unwrap();
448
449 assert_eq!(RawTerm::Binary(vec![1, 2, 3, 4]), out);
450 }
451
452 #[test]
453 fn bitbinary() {
454 let input = read_binary("bins/bitbinary.bin").unwrap();
455 let out = from_bytes(&input).unwrap();
456
457 assert_eq!(
458 RawTerm::BitBinary {
459 binary: vec![95],
460 bit: 23,
461 bits: 5
462 },
463 out
464 );
465 }
466
467 #[test]
468 fn large_string() {
469 let input = read_binary("bins/large_string.bin").unwrap();
470 let out = from_bytes(&input).unwrap();
471
472 if let RawTerm::Binary(x) = &out {
473 assert!(x.starts_with(b"Lorem ipsum dolor sit"))
474 } else {
475 assert!(false)
476 }
477 }
478
479 #[test]
480 fn float() {
481 let input = read_binary("bins/float.bin").unwrap();
482 let out = from_bytes(&input).unwrap();
483
484 assert_eq!(RawTerm::Float(12.515.into()), out);
485 }
486
487 #[test]
488 fn empty_list() {
489 let input = read_binary("bins/empty_list.bin").unwrap();
490 let out = from_bytes(&input).unwrap();
491
492 assert_eq!(RawTerm::Nil, out);
494 }
495
496 #[test]
497 fn number_list() {
498 let input = read_binary("bins/number_list.bin").unwrap();
499 let out = from_bytes(&input).unwrap();
500
501 assert_eq!(RawTerm::String(vec![1, 2, 3, 4]), out);
502 }
503
504 #[test]
505 fn mixed_list() {
506 use crate::RawTerm::*;
507
508 let input = read_binary("bins/mixed_list.bin").unwrap();
509 let out = from_bytes(&input).unwrap();
510
511 assert_eq!(
512 List(vec![
513 SmallInt(1),
514 Binary(b"some".to_vec()),
515 SmallInt(2),
516 Binary(b"text".to_vec())
517 ]),
518 out
519 );
520 }
521
522 #[test]
523 fn improper_list() {
524 use crate::RawTerm::*;
525
526 let input = read_binary("bins/improper_list.bin").unwrap();
527 let out = from_bytes(&input).unwrap();
528
529 assert_eq!(
530 List(vec![
531 SmallInt(1),
532 SmallInt(6),
533 Improper(Box::new(SmallInt(2))),
534 ]),
535 out
536 );
537 }
538
539 #[test]
540 fn atom_map() {
541 let input = read_binary("bins/atom_map.bin").unwrap();
542 let out = from_bytes(&input).unwrap();
543
544 let mut map = Vec::new();
545
546 map.push((
547 RawTerm::AtomDeprecated("just".to_string()),
548 RawTerm::Binary(b"some key".to_vec()),
549 ));
550 map.push((
551 RawTerm::AtomDeprecated("other".to_string()),
552 RawTerm::Binary(b"value".to_vec()),
553 ));
554
555 assert_eq!(RawTerm::Map(map), out);
556 }
557
558 #[test]
559 fn map() {
560 use RawTerm::*;
561
562 let input = read_binary("bins/map.bin").unwrap();
563 if let Map(out) = from_bytes(&input).unwrap() {
564 let mut map = vec![
565 (Binary(b"float".to_vec()), Float(3.14.into())),
566 (
567 List(vec![Binary(b"list as a key".to_vec())]),
568 List(vec![
569 Binary(b"another".to_vec()),
570 Map(vec![(
571 AtomDeprecated("test".to_string()),
572 AtomDeprecated("false".to_string()),
573 )]
574 .into_iter()
575 .collect()),
576 ]),
577 ),
578 (SmallInt(1), Binary(b"one".to_vec())),
579 (
580 AtomDeprecated("tuple".to_string()),
581 SmallTuple(vec![SmallInt(1), AtomDeprecated("more".to_string())]),
582 ),
583 (
584 Binary(b"large".to_vec()),
585 SmallBigInt(BigInt::parse_bytes(b"123456789123456789", 10).unwrap()),
586 ),
587 (
588 Binary(b"nested".to_vec()),
589 Map(vec![(Binary(b"ok".to_vec()), Nil)].into_iter().collect()),
590 ),
591 ];
592
593 for item in out.iter() {
594 if let Some(index) =
595 map.iter()
596 .enumerate()
597 .find_map(|(i, x)| if x == item { Some(i) } else { None })
598 {
599 map.remove(index);
600 } else {
601 panic!("input has more items then expected")
602 }
603 }
604
605 assert!(!out.is_empty());
606 assert!(map.is_empty());
607 } else {
608 assert!(false);
609 }
610 }
611
612 #[test]
613 fn keyword() {
614 let input = read_binary("bins/keyword.bin").unwrap();
615 let out = from_bytes(&input).unwrap();
616
617 let mut map = Vec::new();
618
619 map.push(RawTerm::SmallTuple(vec![
620 RawTerm::AtomDeprecated("just".to_string()),
621 RawTerm::Binary(b"some key".to_vec()),
622 ]));
623 map.push(RawTerm::SmallTuple(vec![
624 RawTerm::AtomDeprecated("other".to_string()),
625 RawTerm::Binary(b"value".to_vec()),
626 ]));
627 map.push(RawTerm::SmallTuple(vec![
628 RawTerm::AtomDeprecated("just".to_string()),
629 RawTerm::Int(1234),
630 ]));
631
632 assert_eq!(RawTerm::List(map), out);
633 }
634
635 #[test]
636 fn tuple() {
637 let input = read_binary("bins/tuple.bin").unwrap();
638 let out = from_bytes(&input).unwrap();
639 assert_eq!(
640 RawTerm::SmallTuple(vec![
641 RawTerm::Binary(b"test".to_vec()),
642 RawTerm::Binary(b"testing".to_vec())
643 ]),
644 out
645 );
646 let large_tuple = read_binary("bins/large_tuple.bin").unwrap();
647 let out = from_bytes(&large_tuple).unwrap();
648 let mut tuple = vec![];
649 for i in 1..401 {
650 if i < 256 {
651 tuple.push(RawTerm::SmallInt(i as u8));
652 } else {
653 tuple.push(RawTerm::Int(i));
654 }
655 }
656 let tuple = RawTerm::SmallTuple(vec![
657 RawTerm::AtomDeprecated("row_data".into()),
658 RawTerm::Binary(b"kkk".to_vec()),
659 RawTerm::LargeTuple(tuple),
660 RawTerm::SmallInt(10),
661 ]);
662 assert_eq!(tuple, out);
663 let bin = tuple.to_bytes();
664 assert_eq!(bin, large_tuple);
665 }
666
667 #[test]
668 fn small_big_int() {
669 let input = read_binary("bins/small_big_int.bin").unwrap();
670 let out = from_bytes(&input).unwrap();
671 assert_eq!(
672 RawTerm::SmallBigInt(BigInt::parse_bytes(b"123456789123456789123456789", 10).unwrap()),
673 out
674 );
675 }
676
677 #[test]
678 fn large_big_int() {
679 use num_traits::pow::Pow;
680
681 let input = read_binary("bins/large_big_int.bin").unwrap();
682 let out = from_bytes(&input).unwrap();
683 let nineninenine = BigUint::parse_bytes(b"999", 10).unwrap();
684
685 assert_eq!(
686 RawTerm::LargeBigInt(BigInt::from(nineninenine.clone().pow(&nineninenine))),
687 out
688 );
689 }
690
691 #[test]
692 fn pid() {
693 let input = read_binary("bins/pid.bin").unwrap();
694 let out = from_bytes(&input).unwrap();
695
696 assert_eq!(
697 RawTerm::Pid {
698 node: Box::new(RawTerm::AtomDeprecated("nonode@nohost".to_string())),
699 id: 91,
700 serial: 0,
701 creation: 0
702 },
703 out
704 );
705 }
706 #[test]
707 fn new_pid() {
708 let input = read_binary("bins/new_pid.bin").unwrap();
709 let out = from_bytes(&input).unwrap();
710 let expect = RawTerm::NewPid {
711 node: Box::new(RawTerm::AtomDeprecated("nonode@nohost".to_string())),
712 id: 79,
713 serial: 0,
714 creation: 0,
715 };
716 assert_eq!(expect, out);
717 assert_eq!(&input, &expect.to_bytes());
718 }
719 #[test]
720 fn function() {
721 let input = read_binary("bins/function.bin").unwrap();
722 let out = from_bytes(&input).unwrap();
723
724 assert_eq!(
725 RawTerm::Function {
726 size: 85,
727 arity: 2,
728 uniq: [149, 84, 239, 178, 136, 29, 208, 62, 138, 103, 212, 245, 20, 90, 180, 225],
729 index: 0,
730 module: Box::new(RawTerm::AtomDeprecated("Elixir.TermGenerator".to_string())),
731 old_index: Box::new(RawTerm::SmallInt(0)),
732 old_uniq: Box::new(RawTerm::Int(78292861)),
733 pid: Box::new(RawTerm::Pid {
734 node: Box::new(RawTerm::AtomDeprecated("nonode@nohost".to_string())),
735 id: 0,
736 serial: 0,
737 creation: 0
738 }),
739 free_var: Vec::new()
740 },
741 out
742 );
743 let input = &[
746 131, 112, 0, 0, 0, 88, 0, 184, 68, 0, 56, 201, 101, 109, 209, 140, 69, 18, 224, 71,
747 189, 151, 33, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 20, 98, 105, 103, 95, 100, 97, 116, 97,
748 95, 114, 101, 100, 105, 115, 95, 83, 85, 73, 84, 69, 97, 0, 98, 5, 194, 32, 1, 88, 100,
749 0, 13, 110, 111, 110, 111, 100, 101, 64, 110, 111, 104, 111, 115, 116, 0, 0, 3, 87, 0,
750 0, 0, 0, 0, 0, 0, 0,
751 ];
752 let expected = RawTerm::Function {
753 size: 88,
754 arity: 0,
755 uniq: [
756 184, 68, 0, 56, 201, 101, 109, 209, 140, 69, 18, 224, 71, 189, 151, 33,
757 ],
758 index: 0,
759 module: Box::new(RawTerm::AtomDeprecated("big_data_redis_SUITE".into())),
760 old_index: Box::new(RawTerm::SmallInt(0)),
761 old_uniq: Box::new(RawTerm::Int(96608257)),
762 pid: Box::new(RawTerm::NewPid {
763 node: Box::new(RawTerm::AtomDeprecated("nonode@nohost".into())),
764 id: 855,
765 serial: 0,
766 creation: 0,
767 }),
768 free_var: Vec::new(),
769 };
770 let out = RawTerm::from_bytes(input).unwrap();
771 assert_eq!(expected, out);
772 assert_eq!(&expected.to_bytes(), input);
773 }
774
775 #[test]
776 fn port() {
777 let input = read_binary("bins/port.bin").unwrap();
778 let out = from_bytes(&input).unwrap();
779
780 assert_eq!(
781 RawTerm::Port {
782 node: Box::new(RawTerm::AtomDeprecated("nonode@nohost".to_string())),
783 id: 3,
784 creation: 0
785 },
786 out
787 );
788 }
789
790 #[test]
791 fn reference() {
792 let input = read_binary("bins/ref.bin").unwrap();
793 let out = from_bytes(&input).unwrap();
794
795 assert_eq!(
796 RawTerm::Ref {
797 node: Box::new(RawTerm::AtomDeprecated("nonode@nohost".to_string())),
798 id: vec![158726, 438566918, 237133],
799 creation: 0
800 },
801 out
802 );
803 }
804
805 #[test]
806 #[cfg(feature = "zlib")]
807 fn gzip() {
808 let input = read_binary("bins/number_list_gzip.bin").unwrap();
809 let out = from_bytes(&input).unwrap();
810 assert!(out.is_list());
811 }
812}
813
814#[cfg(test)]
815mod as_type_tests {
816 use crate::raw_term::RawTermType;
817 use crate::RawTerm;
818
819 #[test]
820 fn as_type_binary() {
821 let term = RawTerm::Binary(vec![1, 2, 3, 4]);
822
823 assert_eq!(RawTermType::Binary, term.as_type())
824 }
825
826 #[test]
827 fn as_type_float() {
828 let term = RawTerm::Float(0.123.into());
829
830 assert_eq!(RawTermType::Float, term.as_type())
831 }
832
833 #[test]
834 fn as_type_nil() {
835 let term = RawTerm::Nil;
836
837 assert_eq!(RawTermType::Nil, term.as_type())
838 }
839
840 #[test]
841 fn as_type_map() {
842 let term = RawTerm::Map(
843 vec![(RawTerm::Atom(String::from("test")), RawTerm::Nil)]
844 .into_iter()
845 .collect(),
846 );
847
848 assert_eq!(RawTermType::Map, term.as_type())
849 }
850}
851
852#[test]
853fn raw_sub_type_ordering() {
854 use RawTermGeneralType::*;
855 assert!(Improper < Number);
859
860 assert!(Number < Atom);
861 assert!(Atom < Reference);
862 assert!(Reference < Fun);
863 assert!(Fun < Port);
864 assert!(Port < Pid);
865 assert!(Pid < Tuple);
866 assert!(Tuple < Map);
867 assert!(Map < Nil);
868 assert!(Nil < List);
869 assert!(List < BitString);
870
871 assert!(Number < BitString);
872 assert!(!(Number > BitString));
873}