Safe MoonBit reader and small encoder for rkyv 0.8 archives
import {
"mizchi/rkyv" @rkyv,
}
let reader = @rkyv.Reader::new(archive_bytes)
let view = reader.read_vec_u32(archive_bytes.length() - 8) catch {
error => abort("invalid rkyv archive: \{error}")
}///|
let envelope = @rkyv.encode_envelope(archive)
///|
let decoded = @rkyv.decode_envelope_with_limit(envelope, 16 * 1024 * 1024) catch {
error => abort("invalid archive transport: \{error}")
}
///|
let view = @catalog.CatalogView::validate(decoded.payload_bytes()) catch {
error => abort("invalid rkyv archive: \{error}")
}///|
let view = reader.read_vec_u32(root_offset) catch {
error => abort("invalid rkyv archive: \{error}")
}
///|
let selected = view.get(index)///|
let user = @rkyv.Schema::Struct([
{ name: "id", schema: @rkyv.Schema::U32 },
{ name: "active", schema: @rkyv.Schema::Bool },
{ name: "name", schema: @rkyv.Schema::String },
{ name: "scores", schema: @rkyv.Schema::VecU32 },
])
///|
let archive = user.encode(
@rkyv.Value::Struct([
{ name: "id", value: @rkyv.Value::U32(42U) },
{ name: "active", value: @rkyv.Value::Bool(true) },
{ name: "name", value: @rkyv.Value::String("Ada") },
{ name: "scores", value: @rkyv.Value::VecU32([7U, 11U, 13U]) },
]),
) catch {
_ => abort("schema and value do not match")
}///|
let root = user.root(archive) catch { _ => abort("invalid archive") }
///|
let name = root.field("name")
///|
let scores = root.field("scores")///|
let archive = user.encode_mut(
@rkyv.Value::Struct([
{ name: "id", value: @rkyv.Value::U32(42U) },
{ name: "active", value: @rkyv.Value::Bool(true) },
{ name: "name", value: @rkyv.Value::String("Ada") },
{ name: "scores", value: @rkyv.Value::VecU32([7U, 11U, 13U]) },
]),
)
///|
let root = user.root_mut(archive.mut_view())
///|
match root.field("id") {
Some(id) => ignore(id.set_u32(99U))
None => abort("missing id")
}
///|
match root.field("scores") {
Some(scores) => match scores.vec_u32_mut() {
Some(scores) => ignore(scores.set(1, 42U))
None => abort("scores is not Vec<u32>")
}
None => abort("missing scores")
}///|
let user = {
name: "User",
fields: [
{ name: "id", typ: UInt32 },
{ name: "active", typ: Bool },
{ name: "name", typ: Text },
{ name: "scores", typ: UInt32Array },
],
}
emit_schema(user)///|
import {
"mizchi/rkyv/examples/host_codegen/generated" @user,
}
///|
let archive = @user.encode(42U, true, "Ada", [7U, 11U, 13U])
///|
let root = @user.UserView::root(Bytes::from_array(archive))
///|
let name : String = root.name()
///|
let scores : @rkyv.U32VecView = root.scores()///|
let archive = @user.encode(42U, true, "Ada", [7U, 11U, 13U])
///|
let writer = @user.UserMutView::root(archive.mut_view())
///|
writer.set_id(99U)
writer.set_active(false)
let patched : Bool = writer.set_name_same_length("Eve")
let scores = writer.scores_mut()
ignore(scores.set(1, 42U))just host-schema
just host-js
# Eve: 3 scoresjust catalog-generate
moon test --target js examples/catalog/client
just catalog-js
# Moon Mug: 1800 cents
just catalog-roundtrip| Operation | MoonBit native | Rust rkyv native |
|---|---|---|
| Checked header + length validation | 6.33 ns | 3.01 ns |
| Validated lazy selected element | 6.84 ns | 1.44 ns |
| Checked root + selected lazy element | 9.81 ns | 3.32 ns |
| Checked eager materialization of all 4K elements | 478.40 ns | 256.22 ns |
| Copy from a validated view to a reused FixedArray / Rust Vec | 200.39 ns | 200.15 ns |
| Checked copy to a reused FixedArray / Rust Vec | 198.22 ns | 201.11 ns |
| Copy to a reused MutArrayView | 1.50 µs | — |
just bench
just bench-profile
just bench-compare
just profile
just host-jsjust fmt
just check
just test
just conformance
just codegenpub suberror RkyvError {
OutOfBounds(offset~ : Int, size~ : Int, length~ : Int)
InvalidPointerWidth(Int)
InvalidAlignment(Int)
InvalidRelativePointer(Int)
LengthOverflow(Int)
InvalidCollectionLength(Int)
InvalidElementSize(Int)
DestinationTooSmall(required~ : Int, actual~ : Int)
InvalidUtf8
InvalidBool(Byte)
InvalidOptionTag(Byte)
InvalidUnionTag(Byte)
DepthLimit(Int)
} derive(Eq, Debug)fn U32VecView::copy_into_mut_view(self : U32VecView, destination : MutArrayView[UInt]) -> Unit raise RkyvErrorfn crc32(bytes : Bytes) -> UIntfn decode_envelope_with_limit(bytes : Bytes, max_payload_length : Int) -> ArchiveEnvelope raise EnvelopeErrorfn encode_envelope(payload : Bytes) -> Bytesfn encode_string(value : String) -> Byteslet envelope_header_size : IntSafe MoonBit reader and small encoder for rkyv 0.8 archives