#marshal #ruby #serialization #deserialize

marshal-rs

闪电般的Rust语言对Ruby语言的Marshal实现

6个版本

新版本 0.2.4 2024年8月23日
0.2.3 2024年8月23日
0.1.0 2024年8月19日

#322 in 编码

Download history 326/week @ 2024-08-16

每月326次下载

自定义许可

70KB
1K SLoC

marshal-rs

marshal-rs是Ruby语言Marshal的Rust实现。

该项目本质上只是@savannstm/marshal,用Rust重写的。它能够以 🔥 闪电般的速度 加载来自Ruby Marshal文件的输出,以及 🔥 闪电般的速度 将其转回Marshal格式。

安装

cargo添加marshal-rs

快速概览

这个crate有两个主要功能:load()dump()

load()接受一个&[u8],它由Marshal数据字节(可以使用std::fs::read()读取)组成,作为其唯一参数,并输出serde_json::Value(如果启用了sonic功能,则为sonic_rs::Value)。

dump()则接受Value作为其唯一参数,并将其反序列化为Vec<u8> Marshal字节流。它不保留字符串的初始编码,将所有字符串都写入UTF-8编码。

注意

marshal-rs**不会**写入对象链接。这意味着输出文件的大小可能比最初更大。否则,它对输出文件没有影响。我**非常**需要帮助写入对象链接。如果你是Ruby/Rust资深人员,并且对Marshal格式非常精通,请考虑向这个仓库提交一个pull request或其他什么。

如果使用表格将Ruby数据序列化为JSON

Ruby对象 序列化为JSON
nil null
1337 (整数) 1337
36893488147419103232 (大整数) { __type: "bigint", value: "36893488147419103232" } (普通对象)
13.37 (浮点数) 13.37
"ligma" (字符串) "ligma"
:ligma (符号) "__symbol__ligma"
/lgma/i (正则表达式) { "__type": "regexp", "expression": "lgma", flags: "i" } (普通对象)
[] (数组) []
{} (哈希) {} (普通对象)
Object.new (包括结构体、模块等) { "__class": "__symbol__Object", "__type": "object" } (普通对象)

字符串

默认情况下,包含编码实例变量的 Ruby 字符串被序列化为 JSON 字符串,而不包含实例变量的字符串被序列化为 { __type: "bytes", data: [...] } 对象。

此行为可以通过 load 函数的 string_mode 参数进行控制。

StringMode::UTF8 尝试将没有实例变量的数组转换为字符串,如果数组是有效的 UTF8,则生成字符串,否则生成对象。

StringMode::Binary 将所有字符串转换为对象。

对象和符号

对于无法在 JSON 中序列化的对象(如对象和符号),marshal-rs 使用将它们字符串化并添加前缀和属性的方法。它将符号字符串化并在其前面添加 __symbol__ 前缀,并将对象的类和类型分别序列化为 __class 键和 __type 键。

哈希键

对于哈希键,在Ruby中可以使用IntegerFloatObject等表示,marshal-rs尝试通过在字符串化键前添加其类型前缀来保留键类型。例如,Ruby的{1 => nil}哈希将被转换为{"__integer__1": null}对象。

实例变量

实例变量始终以字符串形式解码,并带有__symbol__前缀。您可以使用instance_var_prefix参数在load()dump()中管理实例变量的前缀。传递的字符串将替换“@”实例变量的前缀。

不安全代码

此代码在load()函数中多次使用UnsafeCell和unsafe块。然而,在当前实现中,这段不安全代码永远不会引起任何数据竞争或不稳定。

快速示例

use std::fs::read;
use marshal_rs::load::load;
use marshal_rs::dump::dump;

fn main() {
    // Read marshal data
    let marshal_data: Vec<u8> = read("./marshal_file.marshal").unwrap();

    // Serializing to json
    // load() takes a &[u8] as argument, so bytes Vec must be borrowed
    let serialized_to_json: serde_json::Value = load(&marshal_data, None, None);

    // Here you may std::fs::write() serialized JSON to file

    // Serializing back to marshal
    // dump() requires owned Value as argument
    let serialized_to_marshal: Vec<u8> = dump(serialized_to_json, None);

    // Here you may std::fs::write() serialized Marshal data to file
}

MSRV

最低支持的Rust版本是1.63.0。

参考

许可证

本项目采用WTFPL许可。

依赖关系

~4–11MB
~171K SLoC