MoonArrow: pure MoonBit Arrow IPC stream and file reader/writer with checked metadata and PyArrow interoperability.
| 能力 | 当前状态 |
|---|---|
| 列类型 | Null、Boolean、各宽度有/无符号整数、Float32/64、Date32/64、Timestamp、Duration、Utf8/Binary、LargeUtf8/LargeBinary、FixedSizeBinary |
| 复合类型 | List、LargeList、FixedSizeList、Struct、Map、顶层 Int32 索引的 Utf8/Binary Dictionary |
| 空值 | 有效位图、null count、非空字段检查 |
| IPC stream | V5 写入;V4/V5 读取;兼容 legacy 前缀 |
| IPC file | ARROW1 文件、footer 索引、多批次与随机批次读取 |
| 元数据 | schema 与 field 的 UTF-8 key/value,保留顺序、重复键与缺省值 |
| 读取方式 | 整体读入、在已有 Bytes 上逐批解码,或增量推入 stream 字节块 |
| 数据处理 | BatchBuilder、RecordBatch/Table 的投影、筛选、拼接、重分块、摘要 |
| 后端 | Native、JS、Wasm、Wasm-GC 均有测试 |
moon add shunge/arrow@0.2.1import {
"shunge/arrow",
}///|
test "nullable Arrow file roundtrip" {
let schema = @arrow.Schema::new([
@arrow.Field::new("id", Int64, nullable=false),
@arrow.Field::new("name", Utf8),
])
let batch = @arrow.RecordBatch::new(schema, [
Int64s([Some(1L), Some(9007199254740993L)]),
Strings([Some("月兔"), None]),
])
let bytes = @arrow.write_file(schema, [batch])
let reader = @arrow.FileReader::new(bytes)
assert_eq(reader.num_batches(), 1)
let restored = reader.get_batch(0)
assert_true(
restored.columns[0] is Int64s([Some(1L), Some(9007199254740993L)]),
)
assert_true(restored.columns[1] is Strings([Some("月兔"), None]))
}moon run cmd/main --target nativemoon check --target all --deny-warn
moon test --target all
python -m pip install -r tools/requirements-interop.txt
python tools/interop.py --target native
python tools/interop.py --target js
python tools/workflow.py --target native
python tools/count_core.py --min-effective 4001pub(all) suberror ArrowError {
Invalid(String)
Unsupported(String)
LimitExceeded(String)
} derive(Debug)pub struct BatchBuilder {
// private fields
}pub(all) enum Column {
Nulls(Int)
Booleans(Array[Bool?])
Int8s(Array[Int?])
Int16s(Array[Int?])
Int32s(Array[Int?])
Int64s(Array[Int64?])
UInt8s(Array[Int?])
UInt16s(Array[Int?])
UInt32s(Array[UInt?])
UInt64s(Array[UInt64?])
Float32s(Array[Float?])
Float64s(Array[Double?])
Date32s(Array[Int?])
Date64s(Array[Int64?])
Timestamps(Array[Int64?], TimeUnit, String?)
Durations(Array[Int64?], TimeUnit)
Lists(Array[Int], Array[Bool], Column)
LargeLists(Array[Int], Array[Bool], Column)
FixedLists(Array[Bool], Column, Int)
Maps(Array[Int], Array[Bool], Column, Bool)
Structs(Array[Bool], Array[Column])
Dictionaries(Array[Int?], Column, Int64, Bool)
Strings(Array[String?])
Binaries(Array[Bytes?])
LargeStrings(Array[String?])
LargeBinaries(Array[Bytes?])
FixedBinaries(Array[Bytes?], Int)
} derive(Debug)pub(all) enum ColumnRange {
NoRange
IntRange(Int, Int)
Int64Range(Int64, Int64)
UIntRange(UInt, UInt)
UInt64Range(UInt64, UInt64)
Float32Range(Float, Float)
Float64Range(Double, Double)
ByteLengthRange(Int, Int, Int64)
BooleanCounts(Int, Int)
} derive(Debug)fn ColumnSummary::combine(self : ColumnSummary, other : ColumnSummary) -> ColumnSummary raise ArrowErrorpub(all) enum DataType {
Null
Boolean
Int8
Int16
Int32
Int64
UInt8
UInt16
UInt32
UInt64
Float32
Float64
Date32
Date64
Timestamp(TimeUnit, String?)
Duration(TimeUnit)
List
LargeList
FixedSizeList(Int)
Map(Bool)
Struct
Dictionary(Int64, DataType, Bool)
Utf8
Binary
LargeUtf8
LargeBinary
FixedSizeBinary(Int)
} derive(Eq, Debug)pub struct FileIndex {
schema : Schema
batches : Array[MessageInfo]
dictionaries : Array[MessageInfo]
} derive(Debug)pub struct FileWriter {
// private fields
}pub struct IncrementalReader {
// private fields
}fn IncrementalReader::push(self : IncrementalReader, chunk : Bytes) -> Array[RecordBatch] raise ArrowErrorpub struct IncrementalWriter {
// private fields
}fn IncrementalWriter::write_batch(self : IncrementalWriter, batch : RecordBatch) -> Bytes raise ArrowErrorpub(all) struct MessageInfo {
offset : Int
metadata_bytes : Int
body_bytes : Int
kind : MessageKind
rows : Int?
dictionary_id : Int64?
} derive(Debug)pub(all) struct ReadLimits {
max_rows_per_batch : Int
max_values_per_batch : Int
max_fields : Int
max_batches : Int
max_metadata_bytes : Int
max_body_bytes : Int
max_depth : Int
max_dictionary_values : Int
max_dictionary_messages : Int
} derive(Debug)fn RecordBatch::concat(self : RecordBatch, others : Array[RecordBatch]) -> RecordBatch raise ArrowErrorfn RecordBatch::filter_where(self : RecordBatch, predicate : Predicate) -> RecordBatch raise ArrowErrorfn RecordBatch::insert_column(self : RecordBatch, index : Int, field : Field, column : Column) -> RecordBatch raise ArrowErrorfn RecordBatch::new(schema : Schema, columns : Array[Column], num_rows? : Int) -> RecordBatch raise ArrowErrorfn RecordBatch::partition_where(self : RecordBatch, predicate : Predicate) -> (RecordBatch, RecordBatch) raise ArrowErrorfn RecordBatch::rename(self : RecordBatch, index : Int, name : String) -> RecordBatch raise ArrowErrorfn RecordBatch::replace_column(self : RecordBatch, index : Int, field : Field, column : Column) -> RecordBatch raise ArrowErrorfn RecordBatch::slice(self : RecordBatch, start : Int, length : Int) -> RecordBatch raise ArrowErrorfn RecordBatch::split_rows(self : RecordBatch, max_rows : Int) -> Array[RecordBatch] raise ArrowErrorpub struct StreamIndex {
schema : Schema
messages : Array[MessageInfo]
has_eos : Bool
} derive(Debug)pub(all) enum Value {
BooleanValue(Bool)
Int8Value(Int)
Int16Value(Int)
Int32Value(Int)
Int64Value(Int64)
UInt8Value(Int)
UInt16Value(Int)
UInt32Value(UInt)
UInt64Value(UInt64)
Float32Value(Float)
Float64Value(Double)
Date32Value(Int)
Date64Value(Int64)
TimestampValue(Int64)
DurationValue(Int64)
Utf8Value(String)
BinaryValue(Bytes)
LargeUtf8Value(String)
LargeBinaryValue(Bytes)
FixedBinaryValue(Bytes)
ListValue(Array[Value?])
LargeListValue(Array[Value?])
FixedListValue(Array[Value?])
StructValue(Array[Value?])
MapValue(Array[(Value, Value?)])
} derive(Debug)Install
Download zipMoonArrow: pure MoonBit Arrow IPC stream and file reader/writer with checked metadata and PyArrow interoperability.