erlang/
lib.rs

1//-*-Mode:rust;coding:utf-8;tab-width:4;c-basic-offset:4;indent-tabs-mode:()-*-
2//ex: set ft=rust fenc=utf-8 sts=4 ts=4 sw=4 et nomod:
3
4//! # Erlang External Term Format Encoding/Decoding
5//!
6//! Provides all encoding and decoding for the Erlang External Term Format
7//! (as defined at [https://erlang.org/doc/apps/erts/erl_ext_dist.html](https://erlang.org/doc/apps/erts/erl_ext_dist.html)).
8
9// MIT License
10//
11// Copyright (c) 2023 Michael Truog <mjtruog at protonmail dot com>
12//
13// Permission is hereby granted, free of charge, to any person obtaining a
14// copy of this software and associated documentation files (the "Software"),
15// to deal in the Software without restriction, including without limitation
16// the rights to use, copy, modify, merge, publish, distribute, sublicense,
17// and/or sell copies of the Software, and to permit persons to whom the
18// Software is furnished to do so, subject to the following conditions:
19//
20// The above copyright notice and this permission notice shall be included in
21// all copies or substantial portions of the Software.
22//
23// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29// DEALINGS IN THE SOFTWARE.
30
31#![crate_name = "erlang"]
32#![crate_type = "lib"]
33
34use std::collections::BTreeMap;
35
36pub type Result<T> = std::result::Result<T, Error>;
37
38// tag values here http://www.erlang.org/doc/apps/erts/erl_ext_dist.html
39const 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/// f64 comparable data for [`OtpErlangTerm::OtpErlangFloat`]
74#[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/// Pid data for [`OtpErlangTerm::OtpErlangPid`]
94#[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/// Port data for [`OtpErlangTerm::OtpErlangPort`]
104#[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/// Reference data for [`OtpErlangTerm::OtpErlangReference`]
113#[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/// Function data for [`OtpErlangTerm::OtpErlangFunction`]
122#[derive(Debug, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
123pub struct Function {
124    tag: u8,
125    value: Vec<u8>,
126}
127
128/// Erlang term representation
129#[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/// Error description
151#[derive(Debug, Eq, PartialEq)]
152pub enum ErrorKind {
153    OutputError(&'static str),
154    ParseError(&'static str),
155    UnexpectedError(),
156}
157
158/// Error data
159#[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
250/// decodes the Erlang External Term Format into [`OtpErlangTerm`]
251pub 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
269/// encodes [`OtpErlangTerm`] into the Erlang External Term Format
270pub 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)?; // pid
474            let _ = binary_to_atom(i, data)?; // module
475            let _ = binary_to_integer(i, data)?; // index
476            let _ = binary_to_integer(i, data)?; // uniq
477            let _ = binary_to_term_sequence(i, numfree, data)?; // free
478            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    // deprecated
762    // (not used in Erlang/OTP 26, i.e., minor_version 2)
763    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// MIT LICENSE (of tests below)
909//
910// Copyright (c) 2017-2023 Michael Truog <mjtruog at protonmail dot com>
911// Copyright (c) 2009-2013 Dmitry Vasiliev <dima@hlabs.org>
912//
913// Permission is hereby granted, free of charge, to any person obtaining a
914// copy of this software and associated documentation files (the "Software"),
915// to deal in the Software without restriction, including without limitation
916// the rights to use, copy, modify, merge, publish, distribute, sublicense,
917// and/or sell copies of the Software, and to permit persons to whom the
918// Software is furnished to do so, subject to the following conditions:
919//
920// The above copyright notice and this permission notice shall be included in
921// all copies or substantial portions of the Software.
922//
923// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
924// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
925// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
926// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
927// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
928// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
929// DEALINGS IN THE SOFTWARE.
930
931#[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        // concat_bytes! isn't available yet
1359        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