Write and read Apache Fory's cross-language binary format and row format from MoonBit, including schemas, shared and circular values, and reading a single field without building the whole row. Use it when a MoonBit service exchanges data with a Java, Go, Python, Rust or C++ peer over Fory, or when a message has to be decoded field by field.
import {
"moonbitstack/moonfory",
}let greeting = @moonfory.dumps("hello")
let back : String = @moonfory.loads(greeting)
assert_eq(back, "hello")
let numbers = @moonfory.dumps([1, 2, 3])
let same : Array[Int] = @moonfory.loads(numbers)
assert_eq(same, [1, 2, 3])let stream = Buffer()
@moonfory.dump(1, stream)
@moonfory.dump(2, stream)
let cursor = @moonfory.Reader::new(stream.to_bytes())
cursor.read_head()
let first : Int = @moonfory.load(cursor)
cursor.read_head()
let second : Int = @moonfory.load(cursor)
assert_eq((first, second), (1, 2))struct UserId(Int64)
pub impl @moonfory.Codec for UserId with fn ty(_self) -> @moonfory.TypeId {
@moonfory.TypeId::Int64
}
pub impl @moonfory.Codec for UserId with fn write_data(
self,
w : @moonfory.Writer,
) -> Unit raise {
w.write_i64(self.0)
}
pub impl @moonfory.Codec for UserId with fn read_data(
r : @moonfory.Reader,
_ty : @moonfory.TypeId,
) -> UserId raise {
UserId(r.read_i64())
}let point = @moonfory.StructMeta::new("Point", 100, [
@moonfory.FieldMeta::new("x", @moonfory.TypeId::VarInt32),
@moonfory.FieldMeta::new("y", @moonfory.TypeId::VarInt32),
])
let place = @moonfory.Value::Struct(point, [
("x", @moonfory.Value::Int(1L)),
("y", @moonfory.Value::Int(2L)),
])
let place_bytes = @moonfory.dumps(place)
let read_place : @moonfory.Value = @moonfory.loads(
place_bytes, schemas=[point],
)
assert_eq(read_place, place)
assert_eq(@moonfory.dumps(read_place), place_bytes)let node = @moonfory.StructMeta::new("Node", 300, [
@moonfory.FieldMeta::new("val", @moonfory.TypeId::VarInt32),
@moonfory.FieldMeta::new("next", @moonfory.TypeId::Struct, track_ref=true),
])
let cyclic = @moonfory.Value::Struct(node, [
("val", @moonfory.Value::Int(1L)),
("next", @moonfory.Value::Pointer(0)),
])
let cyclic_bytes = @moonfory.dumps(cyclic, track_ref=true)
let back_node : @moonfory.Value = @moonfory.loads(
cyclic_bytes, schemas=[node], track_ref=true,
)
assert_eq(back_node, cyclic)let schema = @moonfory.RowSchema::new([
{ name: "id", ty: @moonfory.RowType::Int64, nullable: false },
{ name: "name", ty: @moonfory.RowType::String, nullable: false },
{ name: "age", ty: @moonfory.RowType::Int32, nullable: true },
])
let record = @moonfory.Row::new(schema)
record.set(0, @moonfory.RowValue::Int64(7L))
record.set(1, @moonfory.RowValue::String("ada"))
record.set(2, @moonfory.RowValue::Null)
let fields = @moonfory.RowCursor::new(record.finish()[:], schema)
assert_eq(fields.get_field(1), @moonfory.RowValue::String("ada"))
assert_eq(fields.is_null(2), true)