Sign in

    parquet

    Parquet reader/writer for MoonBit.

    moonbit
    parquet
    Download zip
    Author
    Version
    0.2.1
    License
    Apache-2.0
    Last updated
    5 months ago
    Downloads
    2K

    Dependencies

    #mizchi/parquet

    Parquet reader/writer for MoonBit.

    #Status

    • Reader passes the vendored apache-parquet-testing fixtures used in this repo:
      • delta_binary_packed
      • delta_byte_array
      • delta_encoding_optional_column
      • delta_encoding_required_column
      • int32_with_null_pages
      • fixed_length_byte_array
      • datapage_v2_empty_datapage.snappy.parquet
      • int96_from_spark
      • alltypes_plain
      • alltypes_dictionary
    • Writer currently supports flat schemas with Int32, Int64, String, and Binary, with Required / Optional repetition.
    • DuckDB interoperability is checked both ways:
      • DuckDB-written parquet can be read by this implementation.
      • MoonBit-written parquet can be read by DuckDB.

    #Benchmark

    Measured on 2026-03-09 on Apple M5, macOS 26.2, Darwin arm64.

    Reproduce:

    just bench-compare-all just bench-compare-rust

    Comparison table from just bench-compare-all:

    benchmarkmoon(js)moon(wasm-gc)moon(native)rust
    read delta binary packed benchmark512.22 us127.01 us645.99 us203.85 us
    read int32 null pages benchmark17.34 us10.85 us43.60 us7.61 us
    read fixed length byte array benchmark87.17 us10.41 us54.68 usunsupported
    read alltypes plain benchmark20.49 us12.02 us45.42 us19.57 us
    read alltypes dictionary benchmark16.83 us11.04 us42.53 us17.31 us
    read int96 from spark benchmark10.90 us3.52 us16.19 us3.28 us
    read empty snappy datapage v2 benchmark3.46 us1.72 us6.27 us2.58 us

    Notes:

    • Rust is the local baseline in tools/rust-bench, built on top of Apache's parquet crate.
    • fixed_length_byte_array is marked unsupported because the current Rust benchmark tool does not read that fixture.
    • On this machine, wasm-gc is the fastest MoonBit target for the read-side microbenchmarks above.

    #Development

    just # check + test just target=js bench just target=wasm-gc bench just target=native bench just bench-compare-all just e2e-duckdb moon info

    #Browser Playground

    The repository includes a browser playground that generates parquet on DuckDB WASM and lets you try SQL against it immediately.

    just playground-install just playground-dev

    Production build:

    just playground-build just playground-build-pages

    In the UI, you can edit schema JSON / rows JSON / SQL, generate parquet bytes with mizchi/parquet, and execute read_parquet('playground.parquet') on the f4ah6o/duckdb WASM backend.

    GitHub Pages:

    https://mizchi.github.io/parquet/

    #License

    Apache-2.0

    ParquetError

    pub(all) suberror ParquetError {
    InvalidData(String)
    Unsupported(String)
    Io(String)
    } derive(Eq)

    Column

    pub struct Column {
    name : String
    column_type : ColumnType
    repetition : Repetition
    } derive(Eq)

    impl Show for Column

    Column::column_type

    fn Column::column_type(self : Column) -> ColumnType

    Column::name

    fn Column::name(self : Column) -> String

    Column::repetition

    fn Column::repetition(self : Column) -> Repetition

    ColumnType

    pub(all) enum ColumnType {
    Boolean
    Int32
    Int64
    TimestampMicros
    Float
    Double
    String
    Binary
    } derive(Eq)

    impl Show for ColumnType

    ParquetColumnData

    pub(all) enum ParquetColumnData {
    Values(Array[Value])
    BooleanValues(Array[Bool])
    Int32Values(Array[Int])
    NullableInt32Values(Array[Int?])
    Int64Values(Array[Int64])
    NullableInt64Values(Array[Int64?])
    TimestampMicrosValues(Array[Int64])
    NullableTimestampMicrosValues(Array[Int64?])
    FloatValues(Array[Float])
    DoubleValues(Array[Double])
    Utf8Values(Array[Bytes])
    NullableUtf8Values(Array[Bytes?])
    BinaryValues(Array[Bytes])
    NullableBinaryValues(Array[Bytes?])
    } derive(Eq)

    ParquetColumnData::length

    fn ParquetColumnData::length(self : ParquetColumnData) -> Int

    ParquetColumnarFile

    pub struct ParquetColumnarFile {
    columns : Array[Column]
    column_data : Array[ParquetColumnData]
    row_count : Int
    column_values_cache : Array[Array[Value]]?
    created_by : String?
    }

    ParquetColumnarFile::column_data

    ParquetColumnarFile::column_values

    ParquetColumnarFile::columns

    ParquetColumnarFile::created_by

    fn ParquetColumnarFile::created_by(self : ParquetColumnarFile) -> String?

    ParquetColumnarFile::row_count

    fn ParquetColumnarFile::row_count(self : ParquetColumnarFile) -> Int

    ParquetFile

    pub struct ParquetFile {
    columns : Array[Column]
    row_count : Int
    column_data : Array[ParquetColumnData]
    rows_cache : Array[Array[Value]]?
    created_by : String?
    }

    impl Eq for ParquetFile
    impl Show for ParquetFile

    ParquetFile::column_data

    fn ParquetFile::column_data(self : ParquetFile) -> Array[ParquetColumnData]

    ParquetFile::columns

    fn ParquetFile::columns(self : ParquetFile) -> Array[Column]

    ParquetFile::created_by

    fn ParquetFile::created_by(self : ParquetFile) -> String?

    ParquetFile::row_count

    fn ParquetFile::row_count(self : ParquetFile) -> Int

    ParquetFile::rows

    fn ParquetFile::rows(self : ParquetFile) -> Array[Array[Value]]

    Repetition

    pub(all) enum Repetition {
    Required
    Optional
    Repeated
    } derive(Eq)

    impl Show for Repetition

    Value

    pub(all) enum Value {
    Boolean(Bool)
    Int32(Int)
    Int64(Int64)
    TimestampMicros(Int64)
    Float(Float)
    Double(Double)
    String(String)
    Binary(Bytes)
    Null
    } derive(Eq)

    impl Show for Value

    new_column

    fn new_column(name : String, column_type : ColumnType, repetition : Repetition) -> Column

    new_parquet_columnar_file

    fn new_parquet_columnar_file(columns : Array[Column], column_data : Array[ParquetColumnData], row_count : Int, created_by : String?) -> ParquetColumnarFile

    new_parquet_file

    fn new_parquet_file(columns : Array[Column], rows : Array[Array[Value]], created_by : String?) -> ParquetFile

    read_bytes

    fn read_bytes(data : Bytes) -> ParquetFile raise ParquetError

    Read a parquet document from bytes.

    read_bytes_columnar

    fn read_bytes_columnar(data : Bytes) -> ParquetColumnarFile raise ParquetError

    Read a parquet document from bytes without row materialization.

    read_file

    fn read_file(path : String) -> ParquetFile raise ParquetError

    Read a parquet file from disk.

    read_file_columnar

    fn read_file_columnar(path : String) -> ParquetColumnarFile raise ParquetError

    Read a parquet file from disk without row materialization.

    write_bytes

    fn write_bytes(file : ParquetFile) -> Bytes raise ParquetError

    Encode a parquet document to bytes.

    The current writer supports flat schemas of Int32, Int64, String, and Binary, with Required or Optional repetition.

    write_file

    fn write_file(path : String, file : ParquetFile) -> Unit raise ParquetError

    Encode a parquet document and write it to disk.

    Powered by MoonBit

    Site sourceReport issuePackagesBuild queueSkillsStatistics

    © 2026 mooncakes.io