Skip to content
High Performance Erlang Term Format Packer
Python C++ JavaScript C Elixir Shell
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
cpp Untangle Unicode for Atoms Jun 25, 2019
ex/erlpack/test
js Added TypeScript typings Oct 26, 2019
py dont catch decode errors Oct 1, 2019
vendor Fixing compile errors and warnings on linux Feb 9, 2016
.gitattributes
.gitignore adds .vscode to gitignore May 6, 2017
.npmignore Ignoring some files not needed inside an NPM package Oct 26, 2019
.travis.yml Update erlpack for Python 3 Jun 24, 2019
COPYING
LICENSE Add ErlPack for Elixir Feb 20, 2017
MANIFEST.in Fix up generating a pip package Jan 20, 2016
README.md Renamed Javascript -> JavaScript Oct 26, 2019
binding.gyp Add zlib Jan 21, 2016
mix.exs
package.json Changed license in package.json to MIT Oct 26, 2019
pytest.ini Update tests for NEW_FLOAT_EXT & ignore vendor directory for pytest. Jan 22, 2016
setup.cfg
setup.py Add required dependency. Aug 14, 2019

README.md

Erlpack

Erlpack is a fast encoder and decoder for the Erlang Term Format (version 131) for Python and JavaScript.

JavaScript

Things that can be packed:

  • Null
  • Booleans
  • Strings
  • Atoms
  • Unicode Strings
  • Floats
  • Integers
  • Longs
  • Longs over 64 bits
  • Objects
  • Arrays
  • Tuples
  • PIDs
  • Ports
  • Exports
  • References

How to pack:

let erlpack = require("erlpack");

packed = erlpack.pack({'a': true, 'list': ['of', 3, 'things', 'to', 'pack']});

How to unpack:

Note: Unpacking requires the binary data be a Uint8Array or Buffer. For those using electron/libchromium see the gotcha below.

let erlpack = require("erlpack");

let unpacked = null;
let packed = new Buffer('', 'binary');
try  {
    unpacked = erlpack.unpack(packed);
}
catch (e) {
    // got an exception parsing
}

Libchromium / Electron Gotcha

Some versions of libchromium replace the native data type backing TypedArrays with a custom data type called blink::WebArrayBuffer. To keep erlpack' dependencies simple this data type is not supported directly. If you're using Electron / Libchromium you need to convert the blink::WebArrayBuffer into a node::Buffer before passing to erlpack. You will need to add this code into your native package somewhere:

v8::Local<v8::Value> ConvertToNodeBuffer(const v8::Local<v8::Object>& blinkArray)
{
    if (node::Buffer::HasInstance(blinkArray)) {
        return blinkArray;
    }
    else if (blinkArray->IsArrayBufferView()) {
        auto byteArray = v8::ArrayBufferView::Cast(*blinkArray);
        return node::Buffer::Copy(v8::Isolate::GetCurrent(), (const char*)byteArray->Buffer()->GetContents().Data(), byteArray->ByteLength()).ToLocalChecked();
    }
    
    return v8::Local<v8::Primitive>(v8::Null(v8::Isolate::GetCurrent()));
}

Then in JavaScript something like:

let packed = NativeUtils.convertToNodeBuffer(new Uint8Array(binaryPayload));
// unpack now using erlpack.unpack(packed)

Python

Things that can be packed:

  • None
  • Booleans
  • Strings
  • Atoms
  • Unicode Strings
  • Floats
  • Integers
  • Longs
  • Longs over 64 bits
  • Dictionaries
  • Lists
  • Tuples
  • User Types (via an encode hook)
  • PIDs
  • Ports
  • Exports
  • References

How to pack:

from erlpack import pack

packed = pack(["thing", "to", "pack"])

How to unpack:

from erlpack import unpack

unpacked = unpack(packed)

How to pack an atom:

from erlpack import Atom, pack

packed = pack(Atom('hello'))

How to use an encode hook.

from erlpack import ErlangTermEncoder

def encode_hook(obj):
    if isinstance(obj, datetime.datetime):
        return obj.isoformat()

encoder = ErlangTermEncoder(encode_hook=encode_hook)
packed = encoder.pack(datetime.datetime(2015, 12, 25, 12, 23, 55))

How to make custom types packable.

from erlpack import pack, Atom

class User(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __erlpack__(self):
        return {
            Atom('name'): self.name,
            Atom('age'): self.age
        }

u = User(name='Jake', age=23)
packed = pack(u)
You can’t perform that action at this time.