1#![crate_name = "erlang"]
32#![crate_type = "lib"]
33
34use std::collections::BTreeMap;
35
36pub type Result<T> = std::result::Result<T, Error>;
37
38const TAG_VERSION: u8 = 131;
40const TAG_COMPRESSED_ZLIB: u8 = 80;
41const TAG_NEW_FLOAT_EXT: u8 = 70;
42const TAG_BIT_BINARY_EXT: u8 = 77;
43const TAG_ATOM_CACHE_REF: u8 = 78;
44const TAG_NEW_PID_EXT: u8 = 88;
45const TAG_NEW_PORT_EXT: u8 = 89;
46const TAG_NEWER_REFERENCE_EXT: u8 = 90;
47const TAG_SMALL_INTEGER_EXT: u8 = 97;
48const TAG_INTEGER_EXT: u8 = 98;
49const TAG_FLOAT_EXT: u8 = 99;
50const TAG_ATOM_EXT: u8 = 100;
51const TAG_REFERENCE_EXT: u8 = 101;
52const TAG_PORT_EXT: u8 = 102;
53const TAG_PID_EXT: u8 = 103;
54const TAG_SMALL_TUPLE_EXT: u8 = 104;
55const TAG_LARGE_TUPLE_EXT: u8 = 105;
56const TAG_NIL_EXT: u8 = 106;
57const TAG_STRING_EXT: u8 = 107;
58const TAG_LIST_EXT: u8 = 108;
59const TAG_BINARY_EXT: u8 = 109;
60const TAG_SMALL_BIG_EXT: u8 = 110;
61const TAG_LARGE_BIG_EXT: u8 = 111;
62const TAG_NEW_FUN_EXT: u8 = 112;
63const TAG_EXPORT_EXT: u8 = 113;
64const TAG_NEW_REFERENCE_EXT: u8 = 114;
65const TAG_SMALL_ATOM_EXT: u8 = 115;
66const TAG_MAP_EXT: u8 = 116;
67const TAG_FUN_EXT: u8 = 117;
68const TAG_ATOM_UTF8_EXT: u8 = 118;
69const TAG_SMALL_ATOM_UTF8_EXT: u8 = 119;
70const TAG_V4_PORT_EXT: u8 = 120;
71const TAG_LOCAL_EXT: u8 = 121;
72
73#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
75pub struct Float {
76 bits: u64,
77}
78
79impl Float {
80 pub fn value(&self) -> f64 {
81 f64::from_bits(self.bits)
82 }
83}
84
85impl From<f64> for Float {
86 fn from(x: f64) -> Self {
87 Float {
88 bits: x.to_bits(),
89 }
90 }
91}
92
93#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
95pub struct Pid {
96 node_tag: u8,
97 node: Vec<u8>,
98 id: Vec<u8>,
99 serial: Vec<u8>,
100 creation: Vec<u8>,
101}
102
103#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
105pub struct Port {
106 node_tag: u8,
107 node: Vec<u8>,
108 id: Vec<u8>,
109 creation: Vec<u8>,
110}
111
112#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
114pub struct Reference {
115 node_tag: u8,
116 node: Vec<u8>,
117 id: Vec<u8>,
118 creation: Vec<u8>,
119}
120
121#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
123pub struct Function {
124 tag: u8,
125 value: Vec<u8>,
126}
127
128#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
130pub enum OtpErlangTerm {
131 OtpErlangInteger(i32),
132 OtpErlangFloat(Float),
133 OtpErlangAtom(Vec<u8>),
134 OtpErlangAtomUTF8(Vec<u8>),
135 OtpErlangAtomCacheRef(u8),
136 OtpErlangAtomBool(bool),
137 OtpErlangString(Vec<u8>),
138 OtpErlangBinary(Vec<u8>),
139 OtpErlangBinaryBits(Vec<u8>, u8),
140 OtpErlangList(Vec<OtpErlangTerm>),
141 OtpErlangListImproper(Vec<OtpErlangTerm>),
142 OtpErlangTuple(Vec<OtpErlangTerm>),
143 OtpErlangMap(BTreeMap<OtpErlangTerm, OtpErlangTerm>),
144 OtpErlangPid(Pid),
145 OtpErlangPort(Port),
146 OtpErlangReference(Reference),
147 OtpErlangFunction(Function),
148}
149
150#[derive(Debug, Eq, PartialEq)]
152pub enum ErrorKind {
153 OutputError(&'static str),
154 ParseError(&'static str),
155 UnexpectedError(),
156}
157
158#[derive(Debug)]
160pub struct Error {
161 kind: ErrorKind,
162 source: Option<Box<dyn std::error::Error + Send + Sync>>,
163}
164
165impl Error {
166 fn new<E>(error: E) -> Self
167 where E: Into<Box<dyn std::error::Error + Send + Sync>>, {
168 Error {
169 kind: ErrorKind::UnexpectedError(),
170 source: Some(error.into()),
171 }
172 }
173}
174
175impl PartialEq<Error> for Error {
176 fn eq(&self, other: &Error) -> bool {
177 self.kind == (*other).kind
178 }
179}
180
181impl std::fmt::Display for Error {
182 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
183 write!(f, "{:?}", self.kind)
184 }
185}
186
187impl std::error::Error for Error {
188 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
189 match &self.source {
190 None => None,
191 Some(e) => Some(&**e),
192 }
193 }
194}
195
196impl From<ErrorKind> for Error {
197 fn from(kind: ErrorKind) -> Self {
198 Error {
199 kind,
200 source: None,
201 }
202 }
203}
204
205impl From<std::num::ParseFloatError> for Error {
206 fn from(error: std::num::ParseFloatError) -> Self {
207 Error::new(error)
208 }
209}
210
211fn slice_get<I>(data: &[u8], index: I) ->
212Result<&<I as std::slice::SliceIndex<[u8]>>::Output>
213where I: std::slice::SliceIndex<[u8]>, {
214 match data.get(index) {
215 Some(result) => Ok(result),
216 None => Err(ErrorKind::ParseError("missing data").into()),
217 }
218}
219
220fn pack_u16(value: u16, data: &mut Vec<u8>) {
221 data.extend_from_slice(&value.to_be_bytes());
222}
223
224fn pack_u32(value: u32, data: &mut Vec<u8>) {
225 data.extend_from_slice(&value.to_be_bytes());
226}
227
228fn pack_u64(value: u64, data: &mut Vec<u8>) {
229 data.extend_from_slice(&value.to_be_bytes());
230}
231
232fn unpack_u16(i: &mut usize, data: &[u8]) -> Result<u16> {
233 let bytes: [u8; 2] = (slice_get(data, *i..*i + 2)?).try_into().unwrap();
234 *i += 2;
235 Ok(u16::from_be_bytes(bytes))
236}
237
238fn unpack_u32(i: &mut usize, data: &[u8]) -> Result<u32> {
239 let bytes: [u8; 4] = (slice_get(data, *i..*i + 4)?).try_into().unwrap();
240 *i += 4;
241 Ok(u32::from_be_bytes(bytes))
242}
243
244fn unpack_f64(i: &mut usize, data: &[u8]) -> Result<f64> {
245 let bytes: [u8; 8] = (slice_get(data, *i..*i + 8)?).try_into().unwrap();
246 *i += 8;
247 Ok(f64::from_bits(u64::from_be_bytes(bytes)))
248}
249
250pub fn binary_to_term(data: &[u8]) -> Result<OtpErlangTerm> {
252 let size = data.len();
253 if size <= 1 {
254 return Err(ErrorKind::ParseError("null input").into());
255 }
256 if data[0] != TAG_VERSION {
257 return Err(ErrorKind::ParseError("invalid version").into());
258 }
259 let mut i: usize = 1;
260 let term = binary_to_term_(&mut i, data)?;
261 if i == size {
262 Ok(term)
263 }
264 else {
265 Err(ErrorKind::ParseError("unparsed data").into())
266 }
267}
268
269pub fn term_to_binary(term: &OtpErlangTerm) -> Result<Vec<u8>> {
271 let mut data: Vec<u8> = Vec::new();
272 data.push(TAG_VERSION);
273 let () = term_to_binary_(term, &mut data)?;
274 Ok(data)
275}
276
277fn binary_to_term_(i: &mut usize, data: &[u8]) -> Result<OtpErlangTerm> {
278 let tag = *slice_get(data, *i)?;
279 *i += 1;
280 match tag {
281 TAG_NEW_FLOAT_EXT => {
282 let float = unpack_f64(i, data)?;
283 Ok(OtpErlangTerm::OtpErlangFloat(float.into()))
284 },
285 TAG_BIT_BINARY_EXT => {
286 let j = unpack_u32(i, data)? as usize;
287 let bits = *slice_get(data, *i)?;
288 *i += 1;
289 let binary = slice_get(data, *i..*i + j)?;
290 *i += j;
291 if bits == 8 {
292 Ok(OtpErlangTerm::OtpErlangBinary(binary.to_vec()))
293 }
294 else {
295 Ok(OtpErlangTerm::OtpErlangBinaryBits(binary.to_vec(), bits))
296 }
297 },
298 TAG_ATOM_CACHE_REF => {
299 let atom = *slice_get(data, *i)?;
300 *i += 1;
301 Ok(OtpErlangTerm::OtpErlangAtomCacheRef(atom))
302 },
303 TAG_SMALL_INTEGER_EXT => {
304 let integer = *slice_get(data, *i)? as i32;
305 *i += 1;
306 Ok(OtpErlangTerm::OtpErlangInteger(integer))
307 },
308 TAG_INTEGER_EXT => {
309 let integer = unpack_u32(i, data)? as i32;
310 Ok(OtpErlangTerm::OtpErlangInteger(integer))
311 },
312 TAG_FLOAT_EXT => {
313 let float_bytes = slice_get(data, *i..*i + 31)?;
314 *i += 31;
315 let float_str = unsafe {
316 std::str::from_utf8_unchecked(float_bytes)
317 };
318 let float = float_str.parse::<f64>()?;
319 Ok(OtpErlangTerm::OtpErlangFloat(float.into()))
320 },
321 TAG_V4_PORT_EXT |
322 TAG_NEW_PORT_EXT |
323 TAG_REFERENCE_EXT |
324 TAG_PORT_EXT => {
325 let (node_tag, node) = binary_to_atom(i, data)?;
326 let id_size = match tag {
327 TAG_V4_PORT_EXT => 8,
328 _ => 4,
329 };
330 let id = slice_get(data, *i..*i + id_size)?;
331 *i += id_size;
332 let creation_size = match tag {
333 TAG_V4_PORT_EXT | TAG_NEW_PORT_EXT => 4,
334 _ => 1,
335 };
336 let creation = slice_get(data, *i..*i + creation_size)?;
337 *i += creation_size;
338 if tag == TAG_REFERENCE_EXT {
339 Ok(OtpErlangTerm::OtpErlangReference(Reference {
340 node_tag,
341 node,
342 id: id.to_vec(),
343 creation: creation.to_vec(),
344 }))
345 }
346 else {
347 Ok(OtpErlangTerm::OtpErlangPort(Port {
348 node_tag,
349 node,
350 id: id.to_vec(),
351 creation: creation.to_vec(),
352 }))
353 }
354 },
355 TAG_NEW_PID_EXT |
356 TAG_PID_EXT => {
357 let (node_tag, node) = binary_to_atom(i, data)?;
358 let id = slice_get(data, *i..*i + 4)?;
359 *i += 4;
360 let serial = slice_get(data, *i..*i + 4)?;
361 *i += 4;
362 let creation_size = if tag == TAG_NEW_PID_EXT { 4 } else { 1 };
363 let creation = slice_get(data, *i..*i + creation_size)?;
364 *i += creation_size;
365 Ok(OtpErlangTerm::OtpErlangPid(Pid {
366 node_tag,
367 node,
368 id: id.to_vec(),
369 serial: serial.to_vec(),
370 creation: creation.to_vec(),
371 }))
372 },
373 TAG_SMALL_TUPLE_EXT => {
374 let length = *slice_get(data, *i)? as usize;
375 *i += 1;
376 let tmp = binary_to_term_sequence(i, length, data)?;
377 Ok(OtpErlangTerm::OtpErlangTuple(tmp))
378 },
379 TAG_LARGE_TUPLE_EXT => {
380 let length = unpack_u32(i, data)? as usize;
381 let tmp = binary_to_term_sequence(i, length, data)?;
382 Ok(OtpErlangTerm::OtpErlangTuple(tmp))
383 },
384 TAG_NIL_EXT => {
385 Ok(OtpErlangTerm::OtpErlangList(Vec::new()))
386 },
387 TAG_STRING_EXT => {
388 let j = unpack_u16(i, data)? as usize;
389 let string = slice_get(data, *i..*i + j)?;
390 *i += j;
391 Ok(OtpErlangTerm::OtpErlangString(string.to_vec()))
392 },
393 TAG_LIST_EXT => {
394 let length = unpack_u32(i, data)? as usize;
395 let mut tmp = binary_to_term_sequence(i, length, data)?;
396 match binary_to_term_(i, data)? {
397 OtpErlangTerm::OtpErlangList(v) if v.is_empty() => {
398 Ok(OtpErlangTerm::OtpErlangList(tmp))
399 },
400 tail => {
401 tmp.push(tail);
402 Ok(OtpErlangTerm::OtpErlangListImproper(tmp))
403 },
404 }
405 },
406 TAG_BINARY_EXT => {
407 let j = unpack_u32(i, data)? as usize;
408 let binary = slice_get(data, *i..*i + j)?;
409 *i += j;
410 Ok(OtpErlangTerm::OtpErlangBinary(binary.to_vec()))
411 },
412 TAG_SMALL_BIG_EXT |
413 TAG_LARGE_BIG_EXT => {
414 Err(ErrorKind::ParseError("rust doesn't provide bigint").into())
415 },
416 TAG_NEW_FUN_EXT => {
417 let length = unpack_u32(i, data)? as usize;
418 let value = slice_get(data, *i..*i + length)?;
419 *i += length;
420 Ok(OtpErlangTerm::OtpErlangFunction(Function {
421 tag,
422 value: value.to_vec(),
423 }))
424 },
425 TAG_EXPORT_EXT => {
426 let i0 = *i;
427 let _ = binary_to_atom(i, data)?;
428 let _ = binary_to_atom(i, data)?;
429 if *slice_get(data, *i)? != TAG_SMALL_INTEGER_EXT {
430 Err(ErrorKind::ParseError("invalid small integer tag").into())
431 }
432 else {
433 *i += 2;
434 let value = slice_get(data, i0..*i)?;
435 Ok(OtpErlangTerm::OtpErlangFunction(Function {
436 tag,
437 value: value.to_vec(),
438 }))
439 }
440 },
441 TAG_NEWER_REFERENCE_EXT |
442 TAG_NEW_REFERENCE_EXT => {
443 let j = (unpack_u16(i, data)? as usize) * 4;
444 let (node_tag, node) = binary_to_atom(i, data)?;
445 let creation_size = match tag {
446 TAG_NEWER_REFERENCE_EXT => 4,
447 _ => 1,
448 };
449 let creation = slice_get(data, *i..*i + creation_size)?;
450 *i += creation_size;
451 let id = slice_get(data, *i..*i + j)?;
452 *i += j;
453 Ok(OtpErlangTerm::OtpErlangReference(Reference {
454 node_tag,
455 node,
456 id: id.to_vec(),
457 creation: creation.to_vec(),
458 }))
459 },
460 TAG_MAP_EXT => {
461 let length = unpack_u32(i, data)? as usize;
462 let mut pairs = BTreeMap::new();
463 for _ in 0..length {
464 let key = binary_to_term_(i, data)?;
465 let value = binary_to_term_(i, data)?;
466 pairs.insert(key, value);
467 }
468 Ok(OtpErlangTerm::OtpErlangMap(pairs))
469 },
470 TAG_FUN_EXT => {
471 let i0 = *i;
472 let numfree = unpack_u32(i, data)? as usize;
473 let _ = binary_to_pid(i, data)?; let _ = binary_to_atom(i, data)?; let _ = binary_to_integer(i, data)?; let _ = binary_to_integer(i, data)?; let _ = binary_to_term_sequence(i, numfree, data)?; let value = slice_get(data, i0..*i)?;
479 Ok(OtpErlangTerm::OtpErlangFunction(Function {
480 tag,
481 value: value.to_vec(),
482 }))
483 },
484 TAG_ATOM_UTF8_EXT |
485 TAG_ATOM_EXT => {
486 let j = unpack_u16(i, data)? as usize;
487 let atom_name = slice_get(data, *i..*i + j)?;
488 *i += j;
489 match atom_name {
490 b"true" => Ok(OtpErlangTerm::OtpErlangAtomBool(true)),
491 b"false" => Ok(OtpErlangTerm::OtpErlangAtomBool(false)),
492 _ if tag == TAG_ATOM_UTF8_EXT => {
493 Ok(OtpErlangTerm::OtpErlangAtomUTF8(atom_name.to_vec()))
494 },
495 _ => Ok(OtpErlangTerm::OtpErlangAtom(atom_name.to_vec())),
496 }
497 },
498 TAG_SMALL_ATOM_UTF8_EXT |
499 TAG_SMALL_ATOM_EXT => {
500 let j = *slice_get(data, *i)? as usize;
501 *i += 1;
502 let atom_name = slice_get(data, *i..*i + j)?;
503 *i += j;
504 match atom_name {
505 b"true" => Ok(OtpErlangTerm::OtpErlangAtomBool(true)),
506 b"false" => Ok(OtpErlangTerm::OtpErlangAtomBool(false)),
507 _ if tag == TAG_SMALL_ATOM_UTF8_EXT => {
508 Ok(OtpErlangTerm::OtpErlangAtomUTF8(atom_name.to_vec()))
509 },
510 _ => Ok(OtpErlangTerm::OtpErlangAtom(atom_name.to_vec())),
511 }
512 },
513 TAG_COMPRESSED_ZLIB => {
514 Err(ErrorKind::ParseError("rust doesn't provide zlib").into())
515 },
516 TAG_LOCAL_EXT => {
517 Err(ErrorKind::ParseError("LOCAL_EXT is opaque").into())
518 },
519 _ => Err(ErrorKind::ParseError("invalid tag").into()),
520 }
521}
522
523fn binary_to_term_sequence(i: &mut usize, length: usize,
524 data: &[u8]) -> Result<Vec<OtpErlangTerm>> {
525 let mut sequence: Vec<OtpErlangTerm> = Vec::new();
526 for _ in 0..length {
527 sequence.push(binary_to_term_(i, data)?);
528 }
529 Ok(sequence)
530}
531
532fn binary_to_integer(i: &mut usize, data: &[u8]) -> Result<OtpErlangTerm> {
533 let tag = *slice_get(data, *i)?;
534 *i += 1;
535 match tag {
536 TAG_SMALL_INTEGER_EXT => {
537 let integer = *slice_get(data, *i)? as i32;
538 *i += 1;
539 Ok(OtpErlangTerm::OtpErlangInteger(integer))
540 },
541 TAG_INTEGER_EXT => {
542 let integer = unpack_u32(i, data)? as i32;
543 Ok(OtpErlangTerm::OtpErlangInteger(integer))
544 },
545 _ => Err(ErrorKind::ParseError("invalid integer tag").into()),
546 }
547}
548
549fn binary_to_pid(i: &mut usize, data: &[u8]) -> Result<OtpErlangTerm> {
550 let tag = *slice_get(data, *i)?;
551 *i += 1;
552 match tag {
553 TAG_NEW_PID_EXT |
554 TAG_PID_EXT => {
555 let (node_tag, node) = binary_to_atom(i, data)?;
556 let id = slice_get(data, *i..*i + 4)?;
557 *i += 4;
558 let serial = slice_get(data, *i..*i + 4)?;
559 *i += 4;
560 let creation_size = if tag == TAG_NEW_PID_EXT { 4 } else { 1 };
561 let creation = slice_get(data, *i..*i + creation_size)?;
562 *i += creation_size;
563 Ok(OtpErlangTerm::OtpErlangPid(Pid {
564 node_tag,
565 node,
566 id: id.to_vec(),
567 serial: serial.to_vec(),
568 creation: creation.to_vec(),
569 }))
570 },
571 _ => Err(ErrorKind::ParseError("invalid pid tag").into()),
572 }
573}
574
575fn binary_to_atom(i: &mut usize, data: &[u8]) -> Result<(u8, Vec<u8>)> {
576 let tag = *slice_get(data, *i)?;
577 *i += 1;
578 match tag {
579 TAG_ATOM_CACHE_REF => {
580 let value = slice_get(data, *i..*i + 1)?;
581 *i += 1;
582 Ok((tag, value.to_vec()))
583 },
584 TAG_ATOM_UTF8_EXT |
585 TAG_ATOM_EXT => {
586 let j = unpack_u16(i, data)? as usize;
587 let value = slice_get(data, *i - 2..*i + j)?;
588 *i += j;
589 Ok((tag, value.to_vec()))
590 },
591 TAG_SMALL_ATOM_UTF8_EXT |
592 TAG_SMALL_ATOM_EXT => {
593 let j = *slice_get(data, *i)? as usize;
594 let value = slice_get(data, *i..*i + 1 + j)?;
595 *i += 1 + j;
596 Ok((tag, value.to_vec()))
597 },
598 _ => Err(ErrorKind::ParseError("invalid atom tag").into()),
599 }
600}
601
602fn term_to_binary_(term: &OtpErlangTerm,
603 data: &mut Vec<u8>) -> Result<()> {
604 match term {
605 OtpErlangTerm::OtpErlangInteger(value) => {
606 integer_to_binary(*value, data)
607 },
608 OtpErlangTerm::OtpErlangFloat(value) => {
609 data.push(TAG_NEW_FLOAT_EXT);
610 pack_u64(value.bits, data);
611 Ok(())
612 },
613 OtpErlangTerm::OtpErlangAtom(value) => {
614 atom_to_binary(value, data)
615 },
616 OtpErlangTerm::OtpErlangAtomUTF8(value) => {
617 atom_utf8_to_binary(value, data)
618 },
619 OtpErlangTerm::OtpErlangAtomCacheRef(value) => {
620 data.push(TAG_ATOM_CACHE_REF);
621 data.push(*value);
622 Ok(())
623 },
624 OtpErlangTerm::OtpErlangAtomBool(value) => {
625 if *value {
626 atom_utf8_to_binary(&b"true".to_vec(), data)
627 }
628 else {
629 atom_utf8_to_binary(&b"false".to_vec(), data)
630 }
631 },
632 OtpErlangTerm::OtpErlangString(value) => {
633 string_to_binary(value, data)
634 },
635 OtpErlangTerm::OtpErlangBinary(value) => {
636 binary_bits_to_binary(value, 8, data)
637 },
638 OtpErlangTerm::OtpErlangBinaryBits(value, bits) => {
639 binary_bits_to_binary(value, *bits, data)
640 },
641 OtpErlangTerm::OtpErlangList(value) => {
642 list_to_binary(value, false, data)
643 },
644 OtpErlangTerm::OtpErlangListImproper(value) => {
645 list_to_binary(value, true, data)
646 },
647 OtpErlangTerm::OtpErlangTuple(value) => {
648 tuple_to_binary(value, data)
649 },
650 OtpErlangTerm::OtpErlangMap(value) => {
651 map_to_binary(value, data)
652 },
653 OtpErlangTerm::OtpErlangPid(value) => {
654 pid_to_binary(value, data)
655 },
656 OtpErlangTerm::OtpErlangPort(value) => {
657 port_to_binary(value, data)
658 },
659 OtpErlangTerm::OtpErlangReference(value) => {
660 reference_to_binary(value, data)
661 },
662 OtpErlangTerm::OtpErlangFunction(value) => {
663 function_to_binary(value, data)
664 },
665 }
666}
667
668fn string_to_binary(value: &Vec<u8>, data: &mut Vec<u8>) -> Result<()> {
669 let length = value.len();
670 if length == 0 {
671 data.push(TAG_NIL_EXT);
672 Ok(())
673 }
674 else if length <= 65535 {
675 data.push(TAG_STRING_EXT);
676 pack_u16(length as u16, data);
677 data.extend(value);
678 Ok(())
679 }
680 else if length <= 4294967295 {
681 data.push(TAG_LIST_EXT);
682 pack_u32(length as u32, data);
683 for c in value.iter() {
684 data.push(TAG_SMALL_INTEGER_EXT);
685 data.push(*c);
686 }
687 data.push(TAG_NIL_EXT);
688 Ok(())
689 }
690 else {
691 Err(ErrorKind::OutputError("u32 overflow").into())
692 }
693}
694
695fn tuple_to_binary(value: &Vec<OtpErlangTerm>,
696 data: &mut Vec<u8>) -> Result<()> {
697 let length = value.len();
698 if length <= 255 {
699 data.push(TAG_SMALL_TUPLE_EXT);
700 data.push(length as u8);
701 for term in value.iter() {
702 let _ = term_to_binary_(term, data)?;
703 }
704 Ok(())
705 }
706 else if length <= 4294967295 {
707 data.push(TAG_LARGE_TUPLE_EXT);
708 pack_u32(length as u32, data);
709 for term in value.iter() {
710 let _ = term_to_binary_(term, data)?;
711 }
712 Ok(())
713 }
714 else {
715 Err(ErrorKind::OutputError("u32 overflow").into())
716 }
717}
718
719fn list_to_binary(value: &Vec<OtpErlangTerm>, improper: bool,
720 data: &mut Vec<u8>) -> Result<()> {
721 let length = value.len();
722 if length == 0 {
723 data.push(TAG_NIL_EXT);
724 Ok(())
725 }
726 else if length <= 4294967295 {
727 data.push(TAG_LIST_EXT);
728 if improper {
729 pack_u32((length - 1) as u32, data);
730 }
731 else {
732 pack_u32(length as u32, data);
733 }
734 for term in value.iter() {
735 let _ = term_to_binary_(term, data)?;
736 }
737 if ! improper {
738 data.push(TAG_NIL_EXT);
739 }
740 Ok(())
741 }
742 else {
743 Err(ErrorKind::OutputError("u32 overflow").into())
744 }
745}
746
747fn integer_to_binary(value: i32, data: &mut Vec<u8>) -> Result<()> {
748 if value >= 0 && value <= 255 {
749 data.push(TAG_SMALL_INTEGER_EXT);
750 data.push(value as u8);
751 Ok(())
752 }
753 else {
754 data.push(TAG_INTEGER_EXT);
755 pack_u32(value as u32, data);
756 Ok(())
757 }
758}
759
760fn atom_to_binary(value: &Vec<u8>, data: &mut Vec<u8>) -> Result<()> {
761 let length = value.len();
764 if length <= 255 {
765 data.push(TAG_SMALL_ATOM_EXT);
766 data.push(length as u8);
767 data.extend(value);
768 Ok(())
769 }
770 else if length <= 65535 {
771 data.push(TAG_ATOM_EXT);
772 pack_u16(length as u16, data);
773 data.extend(value);
774 Ok(())
775 }
776 else {
777 Err(ErrorKind::OutputError("u16 overflow").into())
778 }
779}
780
781fn atom_utf8_to_binary(value: &Vec<u8>, data: &mut Vec<u8>) -> Result<()> {
782 let length = value.len();
783 if length <= 255 {
784 data.push(TAG_SMALL_ATOM_UTF8_EXT);
785 data.push(length as u8);
786 data.extend(value);
787 Ok(())
788 }
789 else if length <= 65535 {
790 data.push(TAG_ATOM_UTF8_EXT);
791 pack_u16(length as u16, data);
792 data.extend(value);
793 Ok(())
794 }
795 else {
796 Err(ErrorKind::OutputError("u16 overflow").into())
797 }
798}
799
800fn binary_bits_to_binary(value: &Vec<u8>, bits: u8,
801 data: &mut Vec<u8>) -> Result<()> {
802 let length = value.len();
803 if bits == 0 {
804 Err(ErrorKind::OutputError("invalid OtpErlangBinaryBits").into())
805 }
806 else if length <= 4294967295 {
807 if bits != 8 {
808 data.push(TAG_BIT_BINARY_EXT);
809 pack_u32(length as u32, data);
810 data.push(bits);
811 }
812 else {
813 data.push(TAG_BINARY_EXT);
814 pack_u32(length as u32, data);
815 }
816 data.extend(value);
817 Ok(())
818 }
819 else {
820 Err(ErrorKind::OutputError("u32 overflow").into())
821 }
822}
823
824fn map_to_binary(value: &BTreeMap<OtpErlangTerm, OtpErlangTerm>,
825 data: &mut Vec<u8>) -> Result<()> {
826 let length = value.len();
827 if length <= 4294967295 {
828 data.push(TAG_MAP_EXT);
829 pack_u32(length as u32, data);
830 for (k, v) in value {
831 let () = term_to_binary_(k, data)?;
832 let () = term_to_binary_(v, data)?;
833 }
834 Ok(())
835 }
836 else {
837 Err(ErrorKind::OutputError("u32 overflow").into())
838 }
839}
840
841fn pid_to_binary(value: &Pid, data: &mut Vec<u8>) -> Result<()> {
842 if value.creation.len() == 4 {
843 data.push(TAG_NEW_PID_EXT);
844 }
845 else {
846 data.push(TAG_PID_EXT);
847 }
848 data.push(value.node_tag);
849 data.extend(&value.node);
850 data.extend(&value.id);
851 data.extend(&value.serial);
852 data.extend(&value.creation);
853 Ok(())
854}
855
856fn port_to_binary(value: &Port, data: &mut Vec<u8>) -> Result<()> {
857 if value.id.len() == 8 {
858 data.push(TAG_V4_PORT_EXT);
859 }
860 else if value.creation.len() == 4 {
861 data.push(TAG_NEW_PORT_EXT);
862 }
863 else {
864 data.push(TAG_PORT_EXT);
865 }
866 data.push(value.node_tag);
867 data.extend(&value.node);
868 data.extend(&value.id);
869 data.extend(&value.creation);
870 Ok(())
871}
872
873fn reference_to_binary(value: &Reference, data: &mut Vec<u8>) -> Result<()> {
874 let length = value.id.len() / 4;
875 if length == 0 {
876 data.push(TAG_REFERENCE_EXT);
877 data.push(value.node_tag);
878 data.extend(&value.node);
879 data.extend(&value.id);
880 data.extend(&value.creation);
881 Ok(())
882 }
883 else if length <= 65535 {
884 if value.creation.len() == 4 {
885 data.push(TAG_NEWER_REFERENCE_EXT);
886 }
887 else {
888 data.push(TAG_NEW_REFERENCE_EXT);
889 }
890 pack_u16(length as u16, data);
891 data.push(value.node_tag);
892 data.extend(&value.node);
893 data.extend(&value.creation);
894 data.extend(&value.id);
895 Ok(())
896 }
897 else {
898 Err(ErrorKind::OutputError("u16 overflow").into())
899 }
900}
901
902fn function_to_binary(value: &Function, data: &mut Vec<u8>) -> Result<()> {
903 data.push(value.tag);
904 data.extend(&value.value);
905 Ok(())
906}
907
908#[cfg(test)]
932mod tests {
933 use crate::*;
934
935 #[test]
936 fn test_pid() {
937 let pid1 = OtpErlangTerm::OtpErlangPid(Pid {
938 node_tag: 100,
939 node: vec![
940 b"\x00\x0d\x6e\x6f\x6e\x6f\x64\x65".to_vec(),
941 b"\x40\x6e\x6f\x68\x6f\x73\x74".to_vec(),
942 ].into_iter().flatten().collect::<Vec<u8>>(),
943 id: b"\x00\x00\x00\x3b".to_vec(),
944 serial: b"\x00\x00\x00\x00".to_vec(),
945 creation: b"\x00".to_vec(),
946 });
947 let binary1 = vec![
948 b"\x83\x67\x64\x00\x0D\x6E\x6F\x6E\x6F\x64\x65".to_vec(),
949 b"\x40\x6E\x6F\x68\x6F\x73\x74\x00\x00\x00\x3B".to_vec(),
950 b"\x00\x00\x00\x00\x00".to_vec(),
951 ].into_iter().flatten().collect::<Vec<u8>>();
952 let pid2 = OtpErlangTerm::OtpErlangPid(Pid {
953 node_tag: 119,
954 node: vec![
955 b"\x0D\x6E\x6F\x6E\x6F\x64\x65\x40".to_vec(),
956 b"\x6E\x6F\x68\x6F\x73\x74".to_vec(),
957 ].into_iter().flatten().collect::<Vec<u8>>(),
958 id: b"\x00\x00\x00\x50".to_vec(),
959 serial: b"\x00\x00\x00\x00".to_vec(),
960 creation: b"\x00".to_vec(),
961 });
962 let binary2 = vec![
963 b"\x83\x67\x77\x0D\x6E\x6F\x6E\x6F\x64\x65\x40".to_vec(),
964 b"\x6E\x6F\x68\x6F\x73\x74\x00\x00\x00\x50\x00".to_vec(),
965 b"\x00\x00\x00\x00".to_vec(),
966 ].into_iter().flatten().collect::<Vec<u8>>();
967 assert_eq!(binary_to_term(binary1.as_slice()).unwrap(), pid1);
968 assert_eq!(term_to_binary(&pid1).unwrap(), binary1.as_slice());
969 assert_eq!(binary_to_term(binary2.as_slice()).unwrap(), pid2);
970 assert_eq!(term_to_binary(&pid2).unwrap(), binary2.as_slice());
971 let pid_old_binary = vec![
972 b"\x83\x67\x64\x00\x0D\x6E\x6F\x6E\x6F\x64\x65".to_vec(),
973 b"\x40\x6E\x6F\x68\x6F\x73\x74\x00\x00\x00\x4E".to_vec(),
974 b"\x00\x00\x00\x00\x00".to_vec(),
975 ].into_iter().flatten().collect::<Vec<u8>>();
976 let pid_old = binary_to_term(pid_old_binary.as_slice()).unwrap();
977 assert_eq!(term_to_binary(&pid_old).unwrap(),
978 pid_old_binary.as_slice());
979 let pid_new_binary = vec![
980 b"\x83\x58\x64\x00\x0D\x6E\x6F\x6E\x6F\x64\x65".to_vec(),
981 b"\x40\x6E\x6F\x68\x6F\x73\x74\x00\x00\x00\x4E".to_vec(),
982 b"\x00\x00\x00\x00\x00\x00\x00\x00".to_vec(),
983 ].into_iter().flatten().collect::<Vec<u8>>();
984 let pid_new = binary_to_term(pid_new_binary.as_slice()).unwrap();
985 assert_eq!(term_to_binary(&pid_new).unwrap(),
986 pid_new_binary.as_slice());
987 }
988
989 #[test]
990 fn test_port() {
991 let port_old_binary = vec![
992 b"\x83\x66\x64\x00\x0D\x6E\x6F\x6E\x6F\x64\x65".to_vec(),
993 b"\x40\x6E\x6F\x68\x6F\x73\x74\x00\x00\x00\x06\x00".to_vec(),
994 ].into_iter().flatten().collect::<Vec<u8>>();
995 let port_old = binary_to_term(port_old_binary.as_slice()).unwrap();
996 assert_eq!(term_to_binary(&port_old).unwrap(),
997 port_old_binary.as_slice());
998 let port_new_binary = vec![
999 b"\x83\x59\x64\x00\x0D\x6E\x6F\x6E\x6F\x64\x65".to_vec(),
1000 b"\x40\x6E\x6F\x68\x6F\x73\x74\x00\x00\x00\x06".to_vec(),
1001 b"\x00\x00\x00\x00".to_vec(),
1002 ].into_iter().flatten().collect::<Vec<u8>>();
1003 let port_new = binary_to_term(port_new_binary.as_slice()).unwrap();
1004 assert_eq!(term_to_binary(&port_new).unwrap(),
1005 port_new_binary.as_slice());
1006 let port_v4_binary = vec![
1007 b"\x83\x78\x77\x0D\x6E\x6F\x6E\x6F\x64\x65\x40".to_vec(),
1008 b"\x6E\x6F\x68\x6F\x73\x74\x00\x00\x00\x00\x00".to_vec(),
1009 b"\x00\x00\x04\x00\x00\x00\x00".to_vec(),
1010 ].into_iter().flatten().collect::<Vec<u8>>();
1011 let port_v4 = binary_to_term(port_v4_binary.as_slice()).unwrap();
1012 assert_eq!(term_to_binary(&port_v4).unwrap(),
1013 port_v4_binary.as_slice());
1014 }
1015
1016 #[test]
1017 fn test_reference() {
1018 let reference1 = OtpErlangTerm::OtpErlangReference(Reference {
1019 node_tag: 100,
1020 node: vec![
1021 b"\x00\x0d\x6e\x6f\x6e\x6f\x64\x65\x40\x6e".to_vec(),
1022 b"\x6f\x68\x6f\x73\x74".to_vec(),
1023 ].into_iter().flatten().collect::<Vec<u8>>(),
1024 id: b"\x00\x00\x00\xaf\x00\x00\x00\x03\x00\x00\x00\x00".to_vec(),
1025 creation: b"\x00".to_vec(),
1026 });
1027 let binary1 = vec![
1028 b"\x83\x72\x00\x03\x64\x00\x0D\x6E\x6F\x6E\x6F".to_vec(),
1029 b"\x64\x65\x40\x6E\x6F\x68\x6F\x73\x74\x00\x00".to_vec(),
1030 b"\x00\x00\xAF\x00\x00\x00\x03\x00\x00\x00\x00".to_vec(),
1031 ].into_iter().flatten().collect::<Vec<u8>>();
1032 assert_eq!(binary_to_term(binary1.as_slice()).unwrap(), reference1);
1033 assert_eq!(term_to_binary(&reference1).unwrap(), binary1.as_slice());
1034 let ref_new_binary = vec![
1035 b"\x83\x72\x00\x03\x64\x00\x0D\x6E\x6F\x6E\x6F".to_vec(),
1036 b"\x64\x65\x40\x6E\x6F\x68\x6F\x73\x74\x00\x00".to_vec(),
1037 b"\x03\xE8\x4E\xE7\x68\x00\x02\xA4\xC8\x53\x40".to_vec(),
1038 ].into_iter().flatten().collect::<Vec<u8>>();
1039 let ref_new = binary_to_term(ref_new_binary.as_slice()).unwrap();
1040 assert_eq!(term_to_binary(&ref_new).unwrap(),
1041 ref_new_binary.as_slice());
1042 let ref_newer_binary = vec![
1043 b"\x83\x5A\x00\x03\x64\x00\x0D\x6E\x6F\x6E\x6F".to_vec(),
1044 b"\x64\x65\x40\x6E\x6F\x68\x6F\x73\x74\x00\x00".to_vec(),
1045 b"\x00\x00\x00\x01\xAC\x03\xC7\x00\x00\x04\xBB".to_vec(),
1046 b"\xB2\xCA\xEE".to_vec(),
1047 ].into_iter().flatten().collect::<Vec<u8>>();
1048 let ref_newer = binary_to_term(ref_newer_binary.as_slice()).unwrap();
1049 assert_eq!(term_to_binary(&ref_newer).unwrap(),
1050 ref_newer_binary.as_slice());
1051 }
1052
1053 #[test]
1054 fn test_function() {
1055 let function1 = OtpErlangTerm::OtpErlangFunction(Function {
1056 tag: 113,
1057 value: vec![
1058 b"\x64\x00\x05\x6c\x69\x73\x74\x73\x64\x00".to_vec(),
1059 b"\x06\x6d\x65\x6d\x62\x65\x72\x61\x02".to_vec(),
1060 ].into_iter().flatten().collect::<Vec<u8>>(),
1061 });
1062 let binary1 = vec![
1063 b"\x83\x71\x64\x00\x05\x6C\x69\x73\x74\x73\x64".to_vec(),
1064 b"\x00\x06\x6D\x65\x6D\x62\x65\x72\x61\x02".to_vec(),
1065 ].into_iter().flatten().collect::<Vec<u8>>();
1066 assert_eq!(binary_to_term(binary1.as_slice()).unwrap(), function1);
1067 assert_eq!(term_to_binary(&function1).unwrap(), binary1.as_slice());
1068 }
1069
1070 #[test]
1071 fn test_decode_basic() {
1072 assert_eq!(binary_to_term(b"").unwrap_err(),
1073 ErrorKind::ParseError("null input").into());
1074 assert_eq!(binary_to_term(b"\x83").unwrap_err(),
1075 ErrorKind::ParseError("null input").into());
1076 assert_eq!(binary_to_term(b"\x83z").unwrap_err(),
1077 ErrorKind::ParseError("invalid tag").into());
1078 }
1079
1080 #[test]
1081 fn test_decode_atom() {
1082 assert_eq!(binary_to_term(b"\x83d").unwrap_err(),
1083 ErrorKind::ParseError("missing data").into());
1084 assert_eq!(binary_to_term(b"\x83d\x00").unwrap_err(),
1085 ErrorKind::ParseError("missing data").into());
1086 assert_eq!(binary_to_term(b"\x83d\x00\x01").unwrap_err(),
1087 ErrorKind::ParseError("missing data").into());
1088 assert_eq!(binary_to_term(b"\x83d\x00\x00").unwrap(),
1089 OtpErlangTerm::OtpErlangAtom(b"".to_vec()));
1090 assert_eq!(binary_to_term(b"\x83s\x00").unwrap(),
1091 OtpErlangTerm::OtpErlangAtom(b"".to_vec()));
1092 assert_eq!(binary_to_term(b"\x83d\x00\x04test").unwrap(),
1093 OtpErlangTerm::OtpErlangAtom(b"test".to_vec()));
1094 assert_eq!(binary_to_term(b"\x83s\x04test").unwrap(),
1095 OtpErlangTerm::OtpErlangAtom(b"test".to_vec()));
1096 }
1097
1098 #[test]
1099 fn test_decode_predefined_atom() {
1100 assert_eq!(binary_to_term(b"\x83s\x04true").unwrap(),
1101 OtpErlangTerm::OtpErlangAtomBool(true));
1102 assert_eq!(binary_to_term(b"\x83s\x05false").unwrap(),
1103 OtpErlangTerm::OtpErlangAtomBool(false));
1104 assert_eq!(binary_to_term(b"\x83s\x09undefined").unwrap(),
1105 OtpErlangTerm::OtpErlangAtom(b"undefined".to_vec()));
1106 assert_eq!(binary_to_term(b"\x83w\x04true").unwrap(),
1107 OtpErlangTerm::OtpErlangAtomBool(true));
1108 assert_eq!(binary_to_term(b"\x83w\x05false").unwrap(),
1109 OtpErlangTerm::OtpErlangAtomBool(false));
1110 assert_eq!(binary_to_term(b"\x83w\x09undefined").unwrap(),
1111 OtpErlangTerm::OtpErlangAtomUTF8(b"undefined".to_vec()));
1112 }
1113
1114 #[test]
1115 fn test_decode_empty_list() {
1116 assert_eq!(binary_to_term(b"\x83j").unwrap(),
1117 OtpErlangTerm::OtpErlangList(Vec::new()));
1118 }
1119
1120 #[test]
1121 fn test_decode_string_list() {
1122 assert_eq!(binary_to_term(b"\x83k").unwrap_err(),
1123 ErrorKind::ParseError("missing data").into());
1124 assert_eq!(binary_to_term(b"\x83k\x00").unwrap_err(),
1125 ErrorKind::ParseError("missing data").into());
1126 assert_eq!(binary_to_term(b"\x83k\x00\x01").unwrap_err(),
1127 ErrorKind::ParseError("missing data").into());
1128 assert_eq!(binary_to_term(b"\x83k\x00\x00").unwrap(),
1129 OtpErlangTerm::OtpErlangString(b"".to_vec()));
1130 assert_eq!(binary_to_term(b"\x83k\x00\x04test").unwrap(),
1131 OtpErlangTerm::OtpErlangString(b"test".to_vec()));
1132 }
1133
1134 #[test]
1135 fn test_decode_list() {
1136 assert_eq!(binary_to_term(b"\x83l").unwrap_err(),
1137 ErrorKind::ParseError("missing data").into());
1138 assert_eq!(binary_to_term(b"\x83l\x00").unwrap_err(),
1139 ErrorKind::ParseError("missing data").into());
1140 assert_eq!(binary_to_term(b"\x83l\x00\x00").unwrap_err(),
1141 ErrorKind::ParseError("missing data").into());
1142 assert_eq!(binary_to_term(b"\x83l\x00\x00\x00").unwrap_err(),
1143 ErrorKind::ParseError("missing data").into());
1144 assert_eq!(binary_to_term(b"\x83l\x00\x00\x00\x00").unwrap_err(),
1145 ErrorKind::ParseError("missing data").into());
1146 assert_eq!(binary_to_term(b"\x83l\x00\x00\x00\x00j").unwrap(),
1147 OtpErlangTerm::OtpErlangList(Vec::new()));
1148 assert_eq!(binary_to_term(b"\x83l\x00\x00\x00\x02jjj").unwrap(),
1149 OtpErlangTerm::OtpErlangList(vec![
1150 OtpErlangTerm::OtpErlangList(Vec::new()),
1151 OtpErlangTerm::OtpErlangList(Vec::new()),
1152 ]));
1153 }
1154
1155 #[test]
1156 fn test_decode_improper_list() {
1157 assert_eq!(binary_to_term(b"\x83l\x00\x00\x00\x00k").unwrap_err(),
1158 ErrorKind::ParseError("missing data").into());
1159 assert_eq!(
1160 binary_to_term(b"\x83l\x00\x00\x00\x01jd\x00\x04tail").unwrap(),
1161 OtpErlangTerm::OtpErlangListImproper(vec![
1162 OtpErlangTerm::OtpErlangList(Vec::new()),
1163 OtpErlangTerm::OtpErlangAtom(b"tail".to_vec()),
1164 ]));
1165 }
1166
1167 #[test]
1168 fn test_decode_small_tuple() {
1169 assert_eq!(binary_to_term(b"\x83h").unwrap_err(),
1170 ErrorKind::ParseError("missing data").into());
1171 assert_eq!(binary_to_term(b"\x83h\x01").unwrap_err(),
1172 ErrorKind::ParseError("missing data").into());
1173 assert_eq!(binary_to_term(b"\x83h\x00").unwrap(),
1174 OtpErlangTerm::OtpErlangTuple(Vec::new()));
1175 assert_eq!(binary_to_term(b"\x83h\x02jj").unwrap(),
1176 OtpErlangTerm::OtpErlangTuple(vec![
1177 OtpErlangTerm::OtpErlangList(Vec::new()),
1178 OtpErlangTerm::OtpErlangList(Vec::new()),
1179 ]));
1180 }
1181
1182 #[test]
1183 fn test_decode_large_tuple() {
1184 assert_eq!(binary_to_term(b"\x83i").unwrap_err(),
1185 ErrorKind::ParseError("missing data").into());
1186 assert_eq!(binary_to_term(b"\x83i\x00").unwrap_err(),
1187 ErrorKind::ParseError("missing data").into());
1188 assert_eq!(binary_to_term(b"\x83i\x00\x00").unwrap_err(),
1189 ErrorKind::ParseError("missing data").into());
1190 assert_eq!(binary_to_term(b"\x83i\x00\x00\x00").unwrap_err(),
1191 ErrorKind::ParseError("missing data").into());
1192 assert_eq!(binary_to_term(b"\x83i\x00\x00\x00\x01").unwrap_err(),
1193 ErrorKind::ParseError("missing data").into());
1194 assert_eq!(binary_to_term(b"\x83i\x00\x00\x00\x00").unwrap(),
1195 OtpErlangTerm::OtpErlangTuple(Vec::new()));
1196 assert_eq!(binary_to_term(b"\x83i\x00\x00\x00\x02jj").unwrap(),
1197 OtpErlangTerm::OtpErlangTuple(vec![
1198 OtpErlangTerm::OtpErlangList(Vec::new()),
1199 OtpErlangTerm::OtpErlangList(Vec::new()),
1200 ]));
1201 }
1202
1203 #[test]
1204 fn test_decode_small_integer() {
1205 assert_eq!(binary_to_term(b"\x83a").unwrap_err(),
1206 ErrorKind::ParseError("missing data").into());
1207 assert_eq!(binary_to_term(b"\x83a\x00").unwrap(),
1208 OtpErlangTerm::OtpErlangInteger(0));
1209 assert_eq!(binary_to_term(b"\x83a\xff").unwrap(),
1210 OtpErlangTerm::OtpErlangInteger(255));
1211 }
1212
1213 #[test]
1214 fn test_decode_integer() {
1215 assert_eq!(binary_to_term(b"\x83b").unwrap_err(),
1216 ErrorKind::ParseError("missing data").into());
1217 assert_eq!(binary_to_term(b"\x83b\x00").unwrap_err(),
1218 ErrorKind::ParseError("missing data").into());
1219 assert_eq!(binary_to_term(b"\x83b\x00\x00").unwrap_err(),
1220 ErrorKind::ParseError("missing data").into());
1221 assert_eq!(binary_to_term(b"\x83b\x00\x00\x00").unwrap_err(),
1222 ErrorKind::ParseError("missing data").into());
1223 assert_eq!(binary_to_term(b"\x83b\x00\x00\x00\x00").unwrap(),
1224 OtpErlangTerm::OtpErlangInteger(0));
1225 assert_eq!(binary_to_term(b"\x83b\x7f\xff\xff\xff").unwrap(),
1226 OtpErlangTerm::OtpErlangInteger(i32::MAX));
1227 assert_eq!(binary_to_term(b"\x83b\x80\x00\x00\x00").unwrap(),
1228 OtpErlangTerm::OtpErlangInteger(i32::MIN));
1229 assert_eq!(binary_to_term(b"\x83b\xff\xff\xff\xff").unwrap(),
1230 OtpErlangTerm::OtpErlangInteger(-1));
1231 }
1232
1233 #[test]
1234 fn test_decode_binary() {
1235 assert_eq!(binary_to_term(b"\x83m").unwrap_err(),
1236 ErrorKind::ParseError("missing data").into());
1237 assert_eq!(binary_to_term(b"\x83m\x00").unwrap_err(),
1238 ErrorKind::ParseError("missing data").into());
1239 assert_eq!(binary_to_term(b"\x83m\x00\x00").unwrap_err(),
1240 ErrorKind::ParseError("missing data").into());
1241 assert_eq!(binary_to_term(b"\x83m\x00\x00\x00").unwrap_err(),
1242 ErrorKind::ParseError("missing data").into());
1243 assert_eq!(binary_to_term(b"\x83m\x00\x00\x00\x01").unwrap_err(),
1244 ErrorKind::ParseError("missing data").into());
1245 assert_eq!(binary_to_term(b"\x83m\x00\x00\x00\x00").unwrap(),
1246 OtpErlangTerm::OtpErlangBinary(Vec::new()));
1247 assert_eq!(binary_to_term(b"\x83m\x00\x00\x00\x04data").unwrap(),
1248 OtpErlangTerm::OtpErlangBinary(b"data".to_vec()));
1249 }
1250
1251 #[test]
1252 fn test_decode_float() {
1253 assert_eq!(binary_to_term(b"\x83F").unwrap_err(),
1254 ErrorKind::ParseError("missing data").into());
1255 assert_eq!(binary_to_term(b"\x83F\x00").unwrap_err(),
1256 ErrorKind::ParseError("missing data").into());
1257 assert_eq!(binary_to_term(b"\x83F\x00\x00").unwrap_err(),
1258 ErrorKind::ParseError("missing data").into());
1259 assert_eq!(binary_to_term(b"\x83F\x00\x00\x00").unwrap_err(),
1260 ErrorKind::ParseError("missing data").into());
1261 assert_eq!(binary_to_term(b"\x83F\x00\x00\x00\x00").unwrap_err(),
1262 ErrorKind::ParseError("missing data").into());
1263 assert_eq!(binary_to_term(b"\x83F\x00\x00\x00\x00\x00").unwrap_err(),
1264 ErrorKind::ParseError("missing data").into());
1265 assert_eq!(
1266 binary_to_term(b"\x83F\x00\x00\x00\x00\x00\x00").unwrap_err(),
1267 ErrorKind::ParseError("missing data").into());
1268 assert_eq!(
1269 binary_to_term(b"\x83F\x00\x00\x00\x00\x00\x00\x00").unwrap_err(),
1270 ErrorKind::ParseError("missing data").into());
1271 assert_eq!(
1272 binary_to_term(b"\x83F\x00\x00\x00\x00\x00\x00\x00\x00").unwrap(),
1273 OtpErlangTerm::OtpErlangFloat(0.0.into()));
1274 assert_eq!(
1275 binary_to_term(b"\x83F?\xf8\x00\x00\x00\x00\x00\x00").unwrap(),
1276 OtpErlangTerm::OtpErlangFloat(1.5.into()));
1277 }
1278
1279 #[test]
1280 fn test_decode_map() {
1281 assert_eq!(binary_to_term(b"\x83t").unwrap_err(),
1282 ErrorKind::ParseError("missing data").into());
1283 assert_eq!(binary_to_term(b"\x83t\x00").unwrap_err(),
1284 ErrorKind::ParseError("missing data").into());
1285 assert_eq!(binary_to_term(b"\x83t\x00\x00").unwrap_err(),
1286 ErrorKind::ParseError("missing data").into());
1287 assert_eq!(binary_to_term(b"\x83t\x00\x00\x00").unwrap_err(),
1288 ErrorKind::ParseError("missing data").into());
1289 assert_eq!(binary_to_term(b"\x83t\x00\x00\x00\x01").unwrap_err(),
1290 ErrorKind::ParseError("missing data").into());
1291 assert_eq!(
1292 binary_to_term(b"\x83t\x00\x00\x00\x00").unwrap(),
1293 OtpErlangTerm::OtpErlangMap(BTreeMap::new()));
1294 let mut map1 = BTreeMap::new();
1295 map1.insert(OtpErlangTerm::OtpErlangAtom(b"a".to_vec()),
1296 OtpErlangTerm::OtpErlangInteger(1));
1297 assert_eq!(
1298 binary_to_term(b"\x83t\x00\x00\x00\x01d\x00\x01aa\x01").unwrap(),
1299 OtpErlangTerm::OtpErlangMap(map1));
1300 let mut map2 = BTreeMap::new();
1301 map2.insert(OtpErlangTerm::OtpErlangBinaryBits(b"\xA8".to_vec(), 6),
1302 OtpErlangTerm::OtpErlangBinary(b"everything".to_vec()));
1303 map2.insert(OtpErlangTerm::OtpErlangAtomUTF8(b"undefined".to_vec()),
1304 OtpErlangTerm::OtpErlangBinary(b"nothing".to_vec()));
1305 let binary2 = vec![
1306 b"\x83\x74\x00\x00\x00\x02\x77\x09\x75\x6E\x64\x65".to_vec(),
1307 b"\x66\x69\x6E\x65\x64\x6D\x00\x00\x00\x07\x6E\x6F".to_vec(),
1308 b"\x74\x68\x69\x6E\x67\x4D\x00\x00\x00\x01\x06\xA8".to_vec(),
1309 b"\x6D\x00\x00\x00\x0A\x65\x76\x65\x72\x79\x74\x68".to_vec(),
1310 b"\x69\x6E\x67".to_vec(),
1311 ].into_iter().flatten().collect::<Vec<u8>>();
1312 assert_eq!(
1313 binary_to_term(binary2.as_slice()).unwrap(),
1314 OtpErlangTerm::OtpErlangMap(map2));
1315 }
1316
1317 #[test]
1318 fn test_encode_tuple() {
1319 assert_eq!(
1320 term_to_binary(&OtpErlangTerm::OtpErlangTuple(vec![])).unwrap(),
1321 b"\x83h\x00");
1322 let tuple1 = OtpErlangTerm::OtpErlangTuple(vec![
1323 OtpErlangTerm::OtpErlangTuple(Vec::new()),
1324 OtpErlangTerm::OtpErlangTuple(vec![]),
1325 ]);
1326 assert_eq!(term_to_binary(&tuple1).unwrap(),
1327 b"\x83h\x02h\x00h\x00");
1328 assert_eq!(
1329 term_to_binary(&OtpErlangTerm::OtpErlangTuple(vec![
1330 OtpErlangTerm::OtpErlangTuple(Vec::new()); 255])).unwrap(),
1331 [b"\x83h\xff",
1332 b"h\x00".repeat(255).as_slice()].concat());
1333 assert_eq!(
1334 term_to_binary(&OtpErlangTerm::OtpErlangTuple(vec![
1335 OtpErlangTerm::OtpErlangTuple(Vec::new()); 256])).unwrap(),
1336 [b"\x83i\x00\x00\x01\x00",
1337 b"h\x00".repeat(256).as_slice()].concat());
1338 }
1339
1340
1341 #[test]
1342 fn test_encode_empty_list() {
1343 assert_eq!(
1344 term_to_binary(&OtpErlangTerm::OtpErlangList(vec![])).unwrap(),
1345 b"\x83j");
1346 }
1347
1348 #[test]
1349 fn test_encode_string_list() {
1350 assert_eq!(
1351 term_to_binary(&OtpErlangTerm::OtpErlangString(
1352 b"".to_vec())).unwrap(),
1353 b"\x83j");
1354 assert_eq!(
1355 term_to_binary(&OtpErlangTerm::OtpErlangString(
1356 b"\x00".to_vec())).unwrap(),
1357 b"\x83k\x00\x01\x00");
1358 let s = vec![
1360 b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r".to_vec(),
1361 b"\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a".to_vec(),
1362 b"\x1b\x1c\x1d\x1e\x1f !\"#$%&'()*+,-./0123456789:;<=>".to_vec(),
1363 b"?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopq".to_vec(),
1364 b"rstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88".to_vec(),
1365 b"\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95".to_vec(),
1366 b"\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2".to_vec(),
1367 b"\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf".to_vec(),
1368 b"\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc".to_vec(),
1369 b"\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9".to_vec(),
1370 b"\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6".to_vec(),
1371 b"\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3".to_vec(),
1372 b"\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0".to_vec(),
1373 b"\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd".to_vec(),
1374 b"\xfe\xff".to_vec(),
1375 ].into_iter().flatten().collect::<Vec<u8>>();
1376 assert_eq!(
1377 term_to_binary(&OtpErlangTerm::OtpErlangString(
1378 s.clone())).unwrap(),
1379 [b"\x83k\x01\x00", s.as_slice()].concat());
1380 }
1381
1382 #[test]
1383 fn test_encode_list_basic() {
1384 assert_eq!(
1385 term_to_binary(&OtpErlangTerm::OtpErlangString(
1386 Vec::new())).unwrap(),
1387 b"\x83\x6A");
1388 assert_eq!(
1389 term_to_binary(&OtpErlangTerm::OtpErlangList(vec![
1390 OtpErlangTerm::OtpErlangString(b"".to_vec())])).unwrap(),
1391 b"\x83\x6C\x00\x00\x00\x01\x6A\x6A");
1392 assert_eq!(
1393 term_to_binary(&OtpErlangTerm::OtpErlangList(vec![
1394 OtpErlangTerm::OtpErlangInteger(1)])).unwrap(),
1395 b"\x83\x6C\x00\x00\x00\x01\x61\x01\x6A");
1396 assert_eq!(
1397 term_to_binary(&OtpErlangTerm::OtpErlangList(vec![
1398 OtpErlangTerm::OtpErlangInteger(255)])).unwrap(),
1399 b"\x83\x6C\x00\x00\x00\x01\x61\xFF\x6A");
1400 assert_eq!(
1401 term_to_binary(&OtpErlangTerm::OtpErlangList(vec![
1402 OtpErlangTerm::OtpErlangInteger(256)])).unwrap(),
1403 b"\x83\x6C\x00\x00\x00\x01\x62\x00\x00\x01\x00\x6A");
1404 assert_eq!(
1405 term_to_binary(&OtpErlangTerm::OtpErlangList(vec![
1406 OtpErlangTerm::OtpErlangInteger(i32::MAX)])).unwrap(),
1407 b"\x83\x6C\x00\x00\x00\x01\x62\x7F\xFF\xFF\xFF\x6A");
1408 assert_eq!(
1409 term_to_binary(&OtpErlangTerm::OtpErlangList(vec![
1410 OtpErlangTerm::OtpErlangInteger(0)])).unwrap(),
1411 b"\x83\x6C\x00\x00\x00\x01\x61\x00\x6A");
1412 assert_eq!(
1413 term_to_binary(&OtpErlangTerm::OtpErlangList(vec![
1414 OtpErlangTerm::OtpErlangInteger(-1)])).unwrap(),
1415 b"\x83\x6C\x00\x00\x00\x01\x62\xFF\xFF\xFF\xFF\x6A");
1416 assert_eq!(
1417 term_to_binary(&OtpErlangTerm::OtpErlangList(vec![
1418 OtpErlangTerm::OtpErlangInteger(-256)])).unwrap(),
1419 b"\x83\x6C\x00\x00\x00\x01\x62\xFF\xFF\xFF\x00\x6A");
1420 assert_eq!(
1421 term_to_binary(&OtpErlangTerm::OtpErlangList(vec![
1422 OtpErlangTerm::OtpErlangInteger(-257)])).unwrap(),
1423 b"\x83\x6C\x00\x00\x00\x01\x62\xFF\xFF\xFE\xFF\x6A");
1424 assert_eq!(
1425 term_to_binary(&OtpErlangTerm::OtpErlangList(vec![
1426 OtpErlangTerm::OtpErlangInteger(i32::MIN)])).unwrap(),
1427 b"\x83\x6C\x00\x00\x00\x01\x62\x80\x00\x00\x00\x6A");
1428 assert_eq!(
1429 term_to_binary(&OtpErlangTerm::OtpErlangList(vec![
1430 OtpErlangTerm::OtpErlangString(b"test".to_vec())])).unwrap(),
1431 b"\x83\x6C\x00\x00\x00\x01\x6B\x00\x04\x74\x65\x73\x74\x6A");
1432 assert_eq!(
1433 term_to_binary(&OtpErlangTerm::OtpErlangList(vec![
1434 OtpErlangTerm::OtpErlangInteger(373),
1435 OtpErlangTerm::OtpErlangInteger(455)])).unwrap(),
1436 [b"\x83\x6C\x00\x00\x00\x02\x62\x00\x00\x01",
1437 b"\x75\x62\x00\x00\x01\xC7\x6A".to_vec().as_slice()].concat());
1438 assert_eq!(
1439 term_to_binary(&OtpErlangTerm::OtpErlangList(vec![
1440 OtpErlangTerm::OtpErlangList(vec![])])).unwrap(),
1441 b"\x83\x6C\x00\x00\x00\x01\x6A\x6A");
1442 assert_eq!(
1443 term_to_binary(&OtpErlangTerm::OtpErlangList(vec![
1444 OtpErlangTerm::OtpErlangList(vec![]),
1445 OtpErlangTerm::OtpErlangList(vec![])])).unwrap(),
1446 b"\x83\x6C\x00\x00\x00\x02\x6A\x6A\x6A");
1447 assert_eq!(
1448 term_to_binary(&OtpErlangTerm::OtpErlangList(vec![
1449 OtpErlangTerm::OtpErlangList(vec![
1450 OtpErlangTerm::OtpErlangString(b"this".to_vec()),
1451 OtpErlangTerm::OtpErlangString(b"is".to_vec())]),
1452 OtpErlangTerm::OtpErlangList(vec![
1453 OtpErlangTerm::OtpErlangList(vec![
1454 OtpErlangTerm::OtpErlangString(b"a".to_vec())])]),
1455 OtpErlangTerm::OtpErlangString(b"test".to_vec()),
1456 ])).unwrap(),
1457 vec![
1458 b"\x83\x6C\x00\x00\x00\x03\x6C\x00".to_vec(),
1459 b"\x00\x00\x02\x6B\x00\x04\x74\x68".to_vec(),
1460 b"\x69\x73\x6B\x00\x02\x69\x73\x6A".to_vec(),
1461 b"\x6C\x00\x00\x00\x01\x6C\x00\x00".to_vec(),
1462 b"\x00\x01\x6B\x00\x01\x61\x6A\x6A".to_vec(),
1463 b"\x6B\x00\x04\x74\x65\x73\x74\x6A".to_vec(),
1464 ].into_iter().flatten().collect::<Vec<u8>>().as_slice());
1465 }
1466
1467 #[test]
1468 fn test_encode_list() {
1469 assert_eq!(
1470 term_to_binary(&OtpErlangTerm::OtpErlangList(vec![
1471 OtpErlangTerm::OtpErlangList(vec![])])).unwrap(),
1472 b"\x83l\x00\x00\x00\x01jj");
1473 assert_eq!(
1474 term_to_binary(&OtpErlangTerm::OtpErlangList(vec![
1475 OtpErlangTerm::OtpErlangList(vec![]),
1476 OtpErlangTerm::OtpErlangList(vec![]),
1477 OtpErlangTerm::OtpErlangList(vec![]),
1478 OtpErlangTerm::OtpErlangList(vec![]),
1479 OtpErlangTerm::OtpErlangList(vec![])])).unwrap(),
1480 b"\x83l\x00\x00\x00\x05jjjjjj");
1481 }
1482
1483 #[test]
1484 fn test_encode_improper_list() {
1485 assert_eq!(
1486 term_to_binary(&OtpErlangTerm::OtpErlangListImproper(vec![
1487 OtpErlangTerm::OtpErlangTuple(vec![]),
1488 OtpErlangTerm::OtpErlangTuple(vec![])])).unwrap(),
1489 b"\x83l\x00\x00\x00\x01h\x00h\x00");
1490 assert_eq!(
1491 term_to_binary(&OtpErlangTerm::OtpErlangListImproper(vec![
1492 OtpErlangTerm::OtpErlangInteger(0),
1493 OtpErlangTerm::OtpErlangInteger(1)])).unwrap(),
1494 b"\x83l\x00\x00\x00\x01a\x00a\x01");
1495 }
1496
1497 #[test]
1498 fn test_encode_unicode() {
1499 assert_eq!(
1500 term_to_binary(&OtpErlangTerm::OtpErlangString(
1501 b"".to_vec())).unwrap(),
1502 b"\x83j");
1503 assert_eq!(
1504 term_to_binary(&OtpErlangTerm::OtpErlangString(
1505 b"test".to_vec())).unwrap(),
1506 b"\x83k\x00\x04test");
1507 assert_eq!(
1508 term_to_binary(&OtpErlangTerm::OtpErlangString(
1509 b"\x00\xc3\xbf".to_vec())).unwrap(),
1510 b"\x83k\x00\x03\x00\xc3\xbf");
1511 assert_eq!(
1512 term_to_binary(&OtpErlangTerm::OtpErlangString(
1513 b"\xc4\x80".to_vec())).unwrap(),
1514 b"\x83k\x00\x02\xc4\x80");
1515 assert_eq!(
1516 term_to_binary(&OtpErlangTerm::OtpErlangString(
1517 b"\xd1\x82\xd0\xb5\xd1\x81\xd1\x82".to_vec())).unwrap(),
1518 b"\x83k\x00\x08\xd1\x82\xd0\xb5\xd1\x81\xd1\x82");
1519 assert_eq!(
1520 term_to_binary(&OtpErlangTerm::OtpErlangString(
1521 b"\xd0\x90".repeat(65536).as_slice().to_vec())).unwrap(),
1522 vec![
1523 b"\x83l\x00\x02\x00\x00".to_vec(),
1524 b"a\xd0a\x90".repeat(65536).as_slice().to_vec(),
1525 b"j".to_vec(),
1526 ].into_iter().flatten().collect::<Vec<u8>>().as_slice());
1527 }
1528
1529 #[test]
1530 fn test_encode_atom() {
1531 assert_eq!(
1532 term_to_binary(&OtpErlangTerm::OtpErlangAtom(
1533 b"".to_vec())).unwrap(),
1534 b"\x83s\x00");
1535 assert_eq!(
1536 term_to_binary(&OtpErlangTerm::OtpErlangAtom(
1537 b"test".to_vec())).unwrap(),
1538 b"\x83s\x04test");
1539 assert_eq!(
1540 term_to_binary(&OtpErlangTerm::OtpErlangAtomUTF8(
1541 b"".to_vec())).unwrap(),
1542 b"\x83w\x00");
1543 assert_eq!(
1544 term_to_binary(&OtpErlangTerm::OtpErlangAtomUTF8(
1545 b"test".to_vec())).unwrap(),
1546 b"\x83w\x04test");
1547 }
1548
1549 #[test]
1550 fn test_encode_string_basic() {
1551 assert_eq!(
1552 term_to_binary(&OtpErlangTerm::OtpErlangString(
1553 b"".to_vec())).unwrap(),
1554 b"\x83\x6A");
1555 assert_eq!(
1556 term_to_binary(&OtpErlangTerm::OtpErlangString(
1557 b"test".to_vec())).unwrap(),
1558 b"\x83\x6B\x00\x04\x74\x65\x73\x74");
1559 assert_eq!(
1560 term_to_binary(&OtpErlangTerm::OtpErlangString(
1561 b"two words".to_vec())).unwrap(),
1562 b"\x83\x6B\x00\x09\x74\x77\x6F\x20\x77\x6F\x72\x64\x73");
1563 assert_eq!(
1564 term_to_binary(&OtpErlangTerm::OtpErlangString(
1565 b"testing multiple words".to_vec())).unwrap(),
1566 vec![
1567 b"\x83\x6B\x00\x16\x74\x65\x73\x74\x69\x6E".to_vec(),
1568 b"\x67\x20\x6D\x75\x6C\x74\x69\x70\x6C\x65".to_vec(),
1569 b"\x20\x77\x6F\x72\x64\x73".to_vec(),
1570 ].into_iter().flatten().collect::<Vec<u8>>().as_slice());
1571 assert_eq!(
1572 term_to_binary(&OtpErlangTerm::OtpErlangString(
1573 b" ".to_vec())).unwrap(),
1574 b"\x83\x6B\x00\x01\x20");
1575 assert_eq!(
1576 term_to_binary(&OtpErlangTerm::OtpErlangString(
1577 b" ".to_vec())).unwrap(),
1578 b"\x83\x6B\x00\x02\x20\x20");
1579 assert_eq!(
1580 term_to_binary(&OtpErlangTerm::OtpErlangString(
1581 b"1".to_vec())).unwrap(),
1582 b"\x83\x6B\x00\x01\x31");
1583 assert_eq!(
1584 term_to_binary(&OtpErlangTerm::OtpErlangString(
1585 b"37".to_vec())).unwrap(),
1586 b"\x83\x6B\x00\x02\x33\x37");
1587 assert_eq!(
1588 term_to_binary(&OtpErlangTerm::OtpErlangString(
1589 b"one = 1".to_vec())).unwrap(),
1590 b"\x83\x6B\x00\x07\x6F\x6E\x65\x20\x3D\x20\x31");
1591 assert_eq!(
1592 term_to_binary(&OtpErlangTerm::OtpErlangString(
1593 b"!@#$%^&*()_+-=[]{}\\|;':\",./<>?~`".to_vec())).unwrap(),
1594 vec![
1595 b"\x83\x6B\x00\x20\x21\x40\x23\x24\x25\x5E\x26\x2A".to_vec(),
1596 b"\x28\x29\x5F\x2B\x2D\x3D\x5B\x5D\x7B\x7D\x5C\x7C".to_vec(),
1597 b"\x3B\x27\x3A\x22\x2C\x2E\x2F\x3C\x3E\x3F\x7E\x60".to_vec(),
1598 ].into_iter().flatten().collect::<Vec<u8>>().as_slice());
1599 assert_eq!(
1600 term_to_binary(&OtpErlangTerm::OtpErlangString(
1601 b"\"\x08\x0c\n\r\t\x0bS\x12".to_vec())).unwrap(),
1602 b"\x83\x6B\x00\x09\x22\x08\x0C\x0A\x0D\x09\x0B\x53\x12");
1603 }
1604
1605 #[test]
1606 fn test_encode_string() {
1607 assert_eq!(
1608 term_to_binary(&OtpErlangTerm::OtpErlangString(
1609 b"".to_vec())).unwrap(),
1610 b"\x83j");
1611 assert_eq!(
1612 term_to_binary(&OtpErlangTerm::OtpErlangString(
1613 b"test".to_vec())).unwrap(),
1614 b"\x83k\x00\x04test");
1615 }
1616
1617 #[test]
1618 fn test_encode_boolean() {
1619 assert_eq!(
1620 term_to_binary(&OtpErlangTerm::OtpErlangAtomBool(true)).unwrap(),
1621 b"\x83w\x04true");
1622 assert_eq!(
1623 term_to_binary(&OtpErlangTerm::OtpErlangAtomBool(false)).unwrap(),
1624 b"\x83w\x05false");
1625 }
1626
1627 #[test]
1628 fn test_encode_small_integer() {
1629 assert_eq!(
1630 term_to_binary(&OtpErlangTerm::OtpErlangInteger(0)).unwrap(),
1631 b"\x83a\x00");
1632 assert_eq!(
1633 term_to_binary(&OtpErlangTerm::OtpErlangInteger(255)).unwrap(),
1634 b"\x83a\xff");
1635 }
1636
1637 #[test]
1638 fn test_encode_integer() {
1639 assert_eq!(
1640 term_to_binary(&OtpErlangTerm::OtpErlangInteger(-1)).unwrap(),
1641 b"\x83b\xff\xff\xff\xff");
1642 assert_eq!(
1643 term_to_binary(&OtpErlangTerm::OtpErlangInteger(i32::MIN)).unwrap(),
1644 b"\x83b\x80\x00\x00\x00");
1645 assert_eq!(
1646 term_to_binary(&OtpErlangTerm::OtpErlangInteger(256)).unwrap(),
1647 b"\x83b\x00\x00\x01\x00");
1648 assert_eq!(
1649 term_to_binary(&OtpErlangTerm::OtpErlangInteger(i32::MAX)).unwrap(),
1650 b"\x83b\x7f\xff\xff\xff");
1651 }
1652
1653 #[test]
1654 fn test_encode_float() {
1655 assert_eq!(
1656 term_to_binary(&OtpErlangTerm::OtpErlangFloat(
1657 0.0.into())).unwrap(),
1658 b"\x83F\x00\x00\x00\x00\x00\x00\x00\x00");
1659 assert_eq!(
1660 term_to_binary(&OtpErlangTerm::OtpErlangFloat(
1661 0.5.into())).unwrap(),
1662 b"\x83F?\xe0\x00\x00\x00\x00\x00\x00");
1663 assert_eq!(
1664 term_to_binary(&OtpErlangTerm::OtpErlangFloat(
1665 (-0.5).into())).unwrap(),
1666 b"\x83F\xbf\xe0\x00\x00\x00\x00\x00\x00");
1667 assert_eq!(
1668 term_to_binary(&OtpErlangTerm::OtpErlangFloat(
1669 3.1415926.into())).unwrap(),
1670 b"\x83F@\t!\xfbM\x12\xd8J");
1671 assert_eq!(
1672 term_to_binary(&OtpErlangTerm::OtpErlangFloat(
1673 (-3.1415926).into())).unwrap(),
1674 b"\x83F\xc0\t!\xfbM\x12\xd8J");
1675 }
1676
1677 #[test]
1678 fn test_encode_map() {
1679 assert_eq!(
1680 term_to_binary(
1681 &OtpErlangTerm::OtpErlangMap(BTreeMap::new())).unwrap(),
1682 b"\x83t\x00\x00\x00\x00");
1683 let mut map1 = BTreeMap::new();
1684 map1.insert(OtpErlangTerm::OtpErlangAtom(b"a".to_vec()),
1685 OtpErlangTerm::OtpErlangInteger(1));
1686 assert_eq!(
1687 term_to_binary(&OtpErlangTerm::OtpErlangMap(map1)).unwrap(),
1688 b"\x83t\x00\x00\x00\x01s\x01aa\x01");
1689 let mut map2 = BTreeMap::new();
1690 map2.insert(OtpErlangTerm::OtpErlangBinaryBits(b"\xA8".to_vec(), 6),
1691 OtpErlangTerm::OtpErlangBinary(b"everything".to_vec()));
1692 map2.insert(OtpErlangTerm::OtpErlangAtomUTF8(b"undefined".to_vec()),
1693 OtpErlangTerm::OtpErlangBinary(b"nothing".to_vec()));
1694 assert_eq!(
1695 term_to_binary(&OtpErlangTerm::OtpErlangMap(map2)).unwrap(),
1696 vec![
1697 b"\x83\x74\x00\x00\x00\x02\x77\x09".to_vec(),
1698 b"\x75\x6E\x64\x65\x66\x69\x6E\x65".to_vec(),
1699 b"\x64\x6D\x00\x00\x00\x07\x6E\x6F".to_vec(),
1700 b"\x74\x68\x69\x6E\x67\x4D\x00\x00".to_vec(),
1701 b"\x00\x01\x06\xA8\x6D\x00\x00\x00".to_vec(),
1702 b"\x0A\x65\x76\x65\x72\x79\x74\x68".to_vec(),
1703 b"\x69\x6E\x67".to_vec(),
1704 ].into_iter().flatten().collect::<Vec<u8>>().as_slice());
1705 }
1706}
1707