Llama: MessagePack library for Haxe
Llama is a MessagePack (MsgPack) encoder/decoder library for Haxe.
Llama is intended to be a modern alternative to the msgpack-haxe library with better reusability.
Supported types
MsgPack type | Haxe type |
---|---|
nil | null |
false, true | bool |
uint, int | Int, Int64 |
float | Float |
bin | Bytes |
str | String |
ext | llama.Extension |
array | Array |
map | IMap (llama.AssociativeArray), anon struct |
Limits
- When encoding
Int
, the library assumes it holds a 32-bit value. It will be truncated otherwise. - When decoding
uint 32
, the value will be promoted toInt64
if it does not fit inInt
. - When decoding
uint 64
, the value will be interpreted asInt64
. - The maximum size of a map or length of an array is the upper limit of
Int
(2147483647). - On targets without a integer data type, numbers will be encoded as 32-bit integers wherever possible.
Supported targets
Target | Supported? |
---|---|
JS | Yes |
Lua | Yes |
Flash (SWF) | Yes |
Neko | No. 31-bit integer limitation. |
PHP | Yes |
C++ (CPP) | Yes |
C# (CS) | Yes* |
Java | Yes |
Python | Yes |
HashLink (HL) | Yes |
- On C#, only maps with
IMap<Any,Any>
,IMap<String,Any>
,IMap<Int,Any>
, and anonymous structures are supported.
Getting started
Requires Haxe 4.0+
Install it using haxelib:
haxelib install llama
Or directly from Git repo:
haxelib git llama https://github.com/chfoo/llama.git
Simple interface
To quickly decode and encode, use the simplified interface:
import llama.Llama;
final myData:Bytes = Llama.encode("hello world!");
final myDoc:String = Llama.decode(myData);
Encoder and decoder interface
The advanced interface provides much better control on the decoding and encoding process.
Encoding
The encoder works on a Output
instance such as BytesOutput
or FileOutput
:
final output = new BytesOutput();
final encoder = new Encoder(output);
encoder.encode("hello world!");
final myData = output.getBytes();
If you have any objects that need to be serialized manually, you can provide a custom encoder callback:
encoder.customEncoder = (encoder, object) -> {
if (Std.is(object, MyCustomClass)) {
encoder.encodeString(object.toString());
} else {
throw 'Unsupported object $object';
}
};
If you have any extensions, the class can implement Extension
which the encoder will use for serialization:
class MyCustomExtension implements Extension {
public function new() {}
public function extensionType():Int {
return 123;
}
public function extensionData():Bytes {
return Bytes.ofString("hello world!");
}
}
encoder.encode(new MyCustomExtension());
If there is any object that cannot be encoded, a String
exception will be thrown.
Decoding
The decoder works on a Input
instance such as BytesInput
or FileInput
:
final input = new BytesInput(myData);
final decoder = new Decoder(input);
final object = decoder.decode();
If there is any decoding errors, a String
exception will be thrown.
By default, map
types are decoded to AssociativeArray
implementing IMap
. This class works with any type as the keys, but map operations are O(n) time which can be unsuitable for large maps. If you know the type of the map keys, you can provide a map factory to the decoder:
// StringMap
decoder = new Decoder(input);
decoder.mapFactory = () -> new Map<String,Any>();
// IntMap
decoder = new Decoder(input);
decoder.mapFactory = () -> new Map<Int,Any>();
// anonymous structure
decoder = new Decoder(input);
decoder.mapFactory = () -> {};
To convert any extensions, you can provide a extension handler callback:
decoder.extensionDecoder = (decoder, extension) {
switch extension.extensionType()
case 123:
return new MyCustomType(extension.extensionData());
default:
return extension;
}
};
When parsing untrusted input, the decoder will accept any size and may crash. To avoid this, set the maxMapSize
, maxArrayLength
, maxBytesLength
, and maxRecursionDepth
fields on decoder
.
Further reading
API docs: https://chfoo.github.io/llama/api/
Contributing
If you have any issues or fixes, please file a issue or pull request.
License
See LICENSE file.