Skip to content

moonbit-community/msgpack

Repository files navigation

MoonBit MessagePack Library

This is a MessagePack implementation for MoonBit, ported from Deno's std/msgpack.

Overview

MessagePack is an efficient binary serialization format. It lets you exchange data among multiple languages like JSON, but it's faster and smaller. Small integers are encoded into a single byte, and typical short strings require only one extra byte in addition to the strings themselves.

Features

  • Basic data types: nil, boolean, integers, floats, strings
  • Collections: arrays and maps
  • Binary data: arbitrary byte sequences
  • Efficient encoding: Uses MessagePack's optimized formats (fixint, fixstr, fixarray, fixmap)
  • Round-trip compatibility: Encode and decode with full fidelity
  • Error handling: Comprehensive error types with descriptive messages

Supported Data Types

The library supports encoding and decoding the following types:

  • nil values
  • boolean values (true/false)
  • Integers: 32-bit (Int), 64-bit signed (Int64), 64-bit unsigned (UInt64)
  • Floating-point: 64-bit (Double)
  • UTF-8 strings
  • Binary data (Bytes)
  • Arrays of values
  • Maps with string keys

API Reference

Core Types

enum Value {
  Nil
  Bool(Bool)
  Int(Int)
  Int64(Int64)
  UInt64(UInt64)
  Float(Double)
  String(String)
  Binary(Bytes)
  Array(Array[Value])
  Map(Map[String, Value])
}

enum MsgPackError {
  IOError(String)
  TypeMismatch(String)
  InvalidData(String)
}

Core Functions

// Encode a MessagePack value to bytes
fn encode(value : Value) -> Bytes

// Decode bytes to a MessagePack value
fn decode(data : Bytes) -> Result[Value, MsgPackError]

Value Creation Helpers

fn create_nil() -> Value
fn create_bool(b : Bool) -> Value
fn create_int(i : Int) -> Value
fn create_int64(i : Int64) -> Value
fn create_uint64(u : UInt64) -> Value
fn create_float(f : Double) -> Value
fn create_string(s : String) -> Value
fn create_binary(b : Bytes) -> Value
fn create_array(arr : Array[Value]) -> Value
fn create_map(map : Map[String, Value]) -> Value

Value Conversion Methods

fn Value::to_string(self : Value) -> Result[String, MsgPackError]
fn Value::to_int(self : Value) -> Result[Int, MsgPackError]
fn Value::to_bool(self : Value) -> Result[Bool, MsgPackError]

Usage Examples

Basic Encoding and Decoding

// Create values
let nil_val = create_nil()
let bool_val = create_bool(true)
let int_val = create_int(42)
let str_val = create_string("hello")

// Encode to MessagePack
let nil_encoded = encode(nil_val)    // 1 byte: [0xc0]
let bool_encoded = encode(bool_val)  // 1 byte: [0xc3]
let int_encoded = encode(int_val)    // 1 byte: [0x2a]
let str_encoded = encode(str_val)    // 6 bytes: [0xa5, 'h', 'e', 'l', 'l', 'o']

// Decode from MessagePack
match decode(nil_encoded) {
  Ok(Nil) => println("Successfully decoded nil")
  Ok(_) => println("Wrong type")
  Err(e) => println("Error: " + e.to_string())
}

Working with Collections

// Create an array
let array_val = create_array([
  create_int(1),
  create_int(2), 
  create_int(3)
])

// Create a map
let map = Map::new()
map["name"] = create_string("MoonBit")
map["version"] = create_int(1)
let map_val = create_map(map)

// Encode collections
let array_encoded = encode(array_val)  // [0x93, 0x01, 0x02, 0x03]
let map_encoded = encode(map_val)      // [0x82, ...] 

Round-trip Example

// Original data
let original = create_array([
  create_nil(),
  create_bool(true),
  create_int(42),
  create_string("hello")
])

// Encode and decode
let encoded = encode(original)
match decode(encoded) {
  Ok(decoded) => {
    // `decoded` should be equivalent to `original`
    println("Round-trip successful!")
  }
  Err(e) => println("Round-trip failed: " + e.to_string())
}

MessagePack Format Compliance

This implementation follows the official MessagePack specification. Key format features:

  • Positive fixint (0x00-0x7f): Single-byte encoding for integers 0-127
  • Negative fixint (0xe0-0xff): Single-byte encoding for integers -32 to -1
  • fixstr (0xa0-0xbf): Compact encoding for strings up to 31 bytes
  • fixarray (0x90-0x9f): Compact encoding for arrays up to 15 elements
  • fixmap (0x80-0x8f): Compact encoding for maps up to 15 key-value pairs
  • Extended formats: Support for larger strings, arrays, and maps
  • Type safety: Strong typing prevents encoding/decoding errors

Running the Demo

To see the library in action:

moon run .

This will run a comprehensive demo showing:

  1. Basic type encoding and decoding
  2. Round-trip encoding/decoding tests
  3. MessagePack format verification
  4. Collection handling (arrays and maps)

Current Limitations

This is a basic implementation with some current limitations:

  1. Float encoding: Currently uses placeholder bytes instead of proper IEEE 754 encoding
  2. 64-bit integers: Simplified encoding (currently encoded as 32-bit placeholders)
  3. Binary data: Basic support (currently encodes length headers only)
  4. String encoding: Proper UTF-8 support but simplified length handling
  5. Extended types: MessagePack extension types are not yet implemented

Future Enhancements

  • Proper IEEE 754 float encoding/decoding
  • Full 64-bit integer support
  • Complete binary data handling
  • MessagePack extension types
  • Streaming encoder/decoder for large data
  • Performance optimizations
  • More comprehensive error reporting

Testing

The library includes comprehensive tests covering:

  • Basic type encoding/decoding
  • Round-trip compatibility
  • MessagePack format compliance
  • Error handling
  • Edge cases

Run tests with:

moon test

Contributing

This library was created as a learning exercise in porting JavaScript/TypeScript libraries to MoonBit. Contributions are welcome to improve the implementation and add missing features.

License

This implementation is inspired by and ported from the Deno standard library's MessagePack implementation, which is MIT licensed.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors