Erlang terms
============

Function encode() can encode Python types to Erlang external term format:

    >>> from erlport.erlterms import encode, Atom, String, BitBinary

Binary strings:

    >>> encode("")
    '\x83m\x00\x00\x00\x00'
    >>> encode("test")
    '\x83m\x00\x00\x00\x04test'

Bit binaries:

    >>> encode(BitBinary("", 0))
    '\x83M\x00\x00\x00\x00\x00'
    >>> encode(BitBinary("\x80", 4))
    '\x83M\x00\x00\x00\x01\x04\x80'

Atoms:

    >>> encode(Atom(""))
    '\x83d\x00\x00'
    >>> encode(Atom("test"))
    '\x83d\x00\x04test'

Integer values:

    >>> encode(0)
    '\x83a\x00'
    >>> encode(255)
    '\x83a\xff'
    >>> encode(256)
    '\x83b\x00\x00\x01\x00'
    >>> encode(2147483647)
    '\x83b\x7f\xff\xff\xff'
    >>> encode(-2147483648)
    '\x83b\x80\x00\x00\x00'
    >>> encode(-1)
    '\x83b\xff\xff\xff\xff'

Big integers:

    >>> encode(2147483648)
    '\x83n\x04\x00\x00\x00\x00\x80'
    >>> encode(-2147483649)
    '\x83n\x04\x01\x01\x00\x00\x80'
    >>> encode(256 ** 256) # doctest: +ELLIPSIS
    '\x83o\x00\x00\x01\x01\x00\x00...\x00\x00\x01'
    >>> encode(-256 ** 256) # doctest: +ELLIPSIS
    '\x83o\x00\x00\x01\x01\x01\x00...\x00\x00\x01'

Float values:

    >>> encode(0.0)
    '\x83F\x00\x00\x00\x00\x00\x00\x00\x00'
    >>> encode(1.1)
    '\x83F?\xf1\x99\x99\x99\x99\x99\x9a'
    >>> encode(10.12345)
    '\x83F@$?4\xd6\xa1a\xe5'

Unicode strings:

    >>> encode(u"")
    '\x83j'
    >>> encode(u"test")
    '\x83k\x00\x04test'
    >>> encode(u"\x00\xff")
    '\x83k\x00\x02\x00\xff'
    >>> encode(u"\u0100")
    '\x83l\x00\x00\x00\x01b\x00\x00\x01\x00j'
    >>> encode(unicode("тест", "utf-8"))
    '\x83l\x00\x00\x00\x04b\x00\x00\x04Bb\x00\x00\x045b\x00\x00\x04Ab\x00\x00\x04Bj'
    >>> encode(u"X" * 65536) # doctest: +ELLIPSIS
    '\x83l\x00\x01\x00\x00aXaX...aXaXj'
    >>> encode(unicode("А", "utf-8") * 65536) # doctest: +ELLIPSIS
    '\x83l\x00\x01\x00\x00b\x00\x00\x04\x10...b\x00\x00\x04\x10j'

    >>> encode(String(u""))
    '\x83j'

Lists:

    >>> encode([])
    '\x83j'
    >>> encode([1])
    '\x83k\x00\x01\x01'
    >>> encode([1.0])
    '\x83l\x00\x00\x00\x01F?\xf0\x00\x00\x00\x00\x00\x00j'
    >>> encode([[Atom("test")], "test"])
    '\x83l\x00\x00\x00\x02l\x00\x00\x00\x01d\x00\x04testjm\x00\x00\x00\x04testj'

Tuples:

    >>> encode(())
    '\x83h\x00'
    >>> encode((1,))
    '\x83h\x01a\x01'
    >>> encode((("test",), Atom("test")))
    '\x83h\x02h\x01m\x00\x00\x00\x04testd\x00\x04test'
    >>> encode((1,) * 256) # doctest: +ELLIPSIS
    '\x83i\x00\x00\x01\x00a\x01...a\x01'


Function decode() can decode Erlang external term format to Python types:

    >>> from erlport.erlterms import decode

Binary strings:

    >>> decode('\x83m\x00\x00\x00\x00')
    ('', '')
    >>> decode('\x83m\x00\x00\x00\x04test')
    ('test', '')

Bit binaries:

    >>> decode('\x83M\x00\x00\x00\x00\x00')
    (bits(0, ''), '')
    >>> decode('\x83M\x00\x00\x00\x01\x04\x80')
    (bits(4, '\x80'), '')

Atoms:

    >>> decode('\x83d\x00\x00')
    (atom(), '')
    >>> decode('\x83d\x00\x04test')
    (atom(test), '')

Integer values:

    >>> decode('\x83a\x00')
    (0, '')
    >>> decode('\x83a\xff')
    (255, '')
    >>> decode('\x83b\x00\x00\x01\x00')
    (256, '')
    >>> decode('\x83b\x7f\xff\xff\xff')
    (2147483647, '')
    >>> decode('\x83b\xff\xff\xff\xff')
    (-1, '')

Big integers:

    >>> decode('\x83n\x00\x00')
    (0, '')
    >>> decode('\x83n\x01\x00\xff')
    (255, '')
    >>> decode('\x83n\x04\x00\x00\xca\x9a\x3b')
    (1000000000, '')
    >>> decode('\x83n\x04\x00\xff\xff\xff\x7f')
    (2147483647, '')
    >>> decode('\x83n\x04\x01\xff\xff\xff\x7f')
    (-2147483647, '')

    >>> decode('\x83o\x00\x00\x00\x01\x00\xff')
    (255, '')
    >>> decode('\x83o\x00\x00\x00\x01\x01\xff')
    (-255, '')

Float values:

    >>> decode('\x83F\x00\x00\x00\x00\x00\x00\x00\x00')
    (0.0, '')
    >>> decode('\x83F?\xf1\x99\x99\x99\x99\x99\x9a')
    (1.1000000000000001, '')
    >>> decode('\x83F@$?4\xd6\xa1a\xe5')
    (10.12345, '')

    >>> decode('\x83c0.00000000000000000000e+00\x00\x00\x00\x00\x00')
    (0.0, '')
    >>> decode('\x83c1.10000000000000008882e+00\x00\x00\x00\x00\x00')
    (1.1000000000000001, '')
    >>> decode('\x83c1.01234500000000000597e+01\x00\x00\x00\x00\x00')
    (10.12345, '')

Unicode strings:

    >>> u, t = decode('\x83j')
    >>> String(u), t
    (string(u''), '')
    >>> u, t = decode('\x83k\x00\x04test')
    >>> u
    [116, 101, 115, 116]
    >>> String(u), t
    (string(u'test'), '')
    >>> u, t = decode('\x83l\x00\x00\x00\x04b\x00\x00\x04Bb\x00\x00\x045b\x00\x00\x04Ab\x00\x00\x04Bj')
    >>> u
    [1090, 1077, 1089, 1090]
    >>> String(u), t
    (string(u'\u0442\u0435\u0441\u0442'), '')

    >>> u, t = decode('\x83l\x00\x01\x00\x00' + 'aX' * 65536 + 'j')
    >>> u # doctest: +ELLIPSIS
    [88, 88, ... 88, 88]
    >>> String(u), t # doctest: +ELLIPSIS
    (string(u'XX...XX'), '')

Lists:

    >>> decode('\x83j')
    ([], '')
    >>> decode('\x83l\x00\x00\x00\x01a\x01j')
    ([1], '')
    >>> decode('\x83l\x00\x00\x00\x02l\x00\x00\x00\x01d\x00\x04testjm\x00\x00\x00\x04testj')
    ([[atom(test)], 'test'], '')

Tuples:

    >>> decode('\x83h\x00')
    ((), '')
    >>> decode('\x83h\x01a\x01')
    ((1,), '')
    >>> decode('\x83h\x02h\x01m\x00\x00\x00\x04testd\x00\x04test')
    ((('test',), atom(test)), '')
    >>> decode('\x83i\x00\x00\x01\x00' + 'a\x01' * 256) # doctest: +ELLIPSIS
    ((1, 1, ... 1, 1), '')
