musli

musli

Rust高性能灵活二进制序列化框架

Musli是一款为Rust开发的高性能二进制序列化框架。它提供多种序列化格式,支持#[no_std]和零拷贝序列化,可灵活编码同一Rust类型。Musli具有详细的错误追踪功能,适用于各种序列化场景。该框架在保持高性能的同时不牺牲功能完整性,是Rust生态系统中的一个强大工具。

Musli序列化框架Rust编码解码二进制格式Github开源项目

musli

<img alt="github" src="https://img.shields.io/badge/github-udoprog/musli-8da0cb?style=for-the-badge&logo=github" height="20"> <img alt="crates.io" src="https://yellow-cdn.veclightyear.com/ab5030c0/22094f80-94b4-4283-abfa-d3188a824b1d.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20"> <img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-musli-66c2a5?style=for-the-badge&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" height="20"> <img alt="build status" src="https://img.shields.io/github/actions/workflow/status/udoprog/musli/ci.yml?branch=main&style=for-the-badge" height="20">

卓越的性能,没有任何妥协1

Müsli 是一个灵活、快速且通用的 Rust 二进制序列化框架,与 [serde] 类似。

它提供了一系列格式,每种格式都有其明确记录的特性和权衡。包括 [musli::json] 在内的每种面向字节的序列化方法都完全支持 #[no_std],无论是否使用 alloc。还有一个特别出色的组件提供了简单明了的[零拷贝序列化][zerocopy]底层功能。

<br>

概览

  • 查看 [derives] 了解如何实现 [Encode] 和 [Decode]。
  • 查看 [data_model] 了解 Müsli 的抽象数据模型。
  • 查看[基准测试]和[大小比较]了解该框架的性能。
  • 查看 [tests] 了解该库的测试方法。
  • 查看 [musli::serde] 了解与 [serde] 的无缝兼容性。您可能还想了解 Müsli 与 serde 的区别
<br>

使用方法

Cargo.toml 中添加以下内容,使用您想要的格式

[dependencies] musli = { version = "0.0.123", features = ["storage"] }
<br>

设计

主要工作由 [Encode] 和 [Decode] 派生宏完成,这些宏在 [derives] 模块中有详细文档。

Müsli 基于实现这些特征的类型所表示的模式进行操作。

use musli::{Encode, Decode}; #[derive(Encode, Decode)] struct Person { /* .. 字段 .. */ }

注意 默认情况下,字段由其数字索引标识,如果重新排序字段,索引会发生变化。重命名字段和设置默认命名策略可以通过配置 [derives] 来完成。

提供的二进制序列化格式旨在高效且准确地编码 Rust 中可用的每种类型和数据结构。每种格式都有详细记录的权衡,并旨在使用时完全内存安全。

在内部,我们使用"编码"、"编码"和"解码"这些术语,因为它们与 [serde] 使用的"序列化"、"序列化"和"反序列化"不同,从而使两个库之间的互操作性更加清晰。编码和解码也更具有"二进制序列化"的感觉,这更贴近本框架的重点。

Müsli 的设计原则与 [serde] 类似。依靠 Rust 强大的特征系统来生成可以在很大程度上被优化掉的代码。最终结果应该与手写的高度优化代码非常相似。

例如,以下两个函数都生成相同的汇编代码(使用 --release 构建):

const OPTIONS: Options = options::new() .with_integer(Integer::Fixed) .with_byte_order(ByteOrder::NATIVE) .build(); const ENCODING: Encoding<OPTIONS> = Encoding::new().with_options(); #[derive(Encode, Decode)] #[musli(packed)] pub struct Storage { left: u32, right: u32, } 使用musli的函数: ```rust fn with_musli(storage: &Storage) -> Result<[u8; 8]> { let mut array = [0; 8]; ENCODING.encode(&mut array[..], storage)?; Ok(array) }

不使用musli的函数:

fn without_musli(storage: &Storage) -> Result<[u8; 8]> { let mut array = [0; 8]; array[..4].copy_from_slice(&storage.left.to_ne_bytes()); array[4..].copy_from_slice(&storage.right.to_ne_bytes()); Ok(array) }

Müsli 与 [serde] 的不同之处

Müsli 的数据模型不直接对应 Rust。没有提供被序列化类型元数据的 serialize_struct_variant 方法。[Encoder] 和 [Decoder] trait 对此是不可知的。与 Rust 类型的兼容性完全由 [Encode] 和 [Decode] 派生结合模式来处理。

我们使用 GATs 提供更易用的抽象。当 serde 设计时 GATs 还不可用。

所有东西都是 [Decoder] 或 [Encoder]。因此字段名不限于字符串或索引,而可以根据需要命名为[任意类型][musli-name-type]。

仅在需要时使用访问器serde 在反序列化时[完全使用访问器],相应的方法被视为底层格式的"提示"。然后反序列化器可以根据底层格式实际包含的内容自由调用访问器上的任何方法。在 Müsli 中,我们颠倒了这一点。如果调用者想要解码任意类型,它会调用 [decode_any]。然后格式可以发出适当的底层类型信号,或调用 [Visitor::visit_unknown] 告诉实现者它无法访问类型信息。

我们发明了模式编码 允许同一个 Rust 类型以多种不同方式编码,对编码方式有更大的控制。默认情况下我们包含 [Binary] 和 [Text] 模式,为二进制和基于文本的格式提供合理的默认值。

Müsli 从底层完全支持 [no-std 和 no-alloc],使用安全高效的[作用域分配]而不影响功能。

我们支持[详细跟踪] 解码时可以大大改善出错位置的诊断。

格式

当前格式通过支持不同程度的升级稳定性来区分。完全升级稳定的编码格式必须容忍一个模型可以添加旧版本模型应该能够忽略的字段。

部分升级稳定性仍然有用,就像下面的 [musli::storage] 格式,因为从存储读取只需要解码是升级稳定的。所以如果使用 #[musli(default)] 正确管理,这永远不会导致任何读取者看到未知字段。

可用格式及其功能如下:

reordermissingunknownself
[musli::storage] #[musli(packed)]
[musli::storage]
[musli::wire]
[musli::descriptive]
[musli::json] 2

reorder 决定字段是否必须按照在类型中指定的确切顺序出现。在这种类型中重新排序字段会导致某种未知但安全的行为。这只适用于每个客户端的数据模型严格同步的通信。

missing 决定读取是否可以通过类似 Option<T> 的方式处理缺失字段。这适用于磁盘存储,因为它意味着随着模式的演变可以添加新的可选字段。

unknown 决定格式是否可以跳过未知字段。这适用于网络通信。此时你已经达到了升级稳定性。这里可以进行一些级别的内省,因为序列化格式必须包含足够的字段信息来知道要跳过什么,这通常允许对基本类型进行推理。

self 决定格式是否是自描述的。允许从序列化状态完全重建数据结构。这些格式不需要模型来解码,可以与 [musli::value] 等动态容器相互转换以进行内省。这种格式还允许执行类型强制转换,因此如果符合目标类型,有符号数可以正确读取为无符号数。

每减少一个功能,格式就变得更紧凑高效。例如使用 #[musli(packed)] 的 [musli::storage] 大约与 [bincode] 一样紧凑,而 [musli::wire] 的大小与 [protobuf] 相当。所有格式主要面向字节,但如果好处明显,有些可能会执行[位压缩]。

升级稳定性

以下是使用 [musli::wire] 实现完全升级稳定性的示例。Version1 可以从 Version2 的实例中解码,因为它知道如何跳过属于 Version2 的字段。我们还明确地为字段添加 #[musli(name = ..)],以确保它们在重新排序时不会改变。

use musli::{Encode, Decode}; #[derive(Debug, PartialEq, Encode, Decode)] struct Version1 { #[musli(mode = Binary, name = 0)] name: String, } #[derive(Debug, PartialEq, Encode, Decode)] struct Version2 { #[musli(mode = Binary, name = 0)] name: String, #[musli(mode = Binary, name = 1)] #[musli(default)] age: Option<u32>, } let version2 = musli::wire::to_vec(&Version2 { name: String::from("Aristotle"), age: Some(61), })?; let version1: Version1 = musli::wire::decode(version2.as_slice())?;

以下是使用 [musli::storage] 对相同数据模型实现部分升级稳定性的示例。注意 Version2 如何从 Version1 解码,但不能反过来,这使其适用于磁盘存储,其中模式可以从旧版本演变到新版本。

let version2 = musli::storage::to_vec(&Version2 { name: String::from("Aristotle"), age: Some(61), })?; assert!(musli::storage::decode::<_, Version1>(version2.as_slice()).is_err()); let version1 = musli::storage::to_vec(&Version1 { name: String::from("Aristotle"), })?; let version2: Version2 = musli::storage::decode(version1.as_slice())?;

模式

与 [serde] 相比,在 Müsli 中同一个模型可以以不同的方式序列化。我们支持为单个模型实现不同的模式,而不是要求使用不同的模型。 模式是一种类型参数,它允许根据编码器配置的模式应用不同的属性。模式可以适用于任何musli属性,为您提供了很大的灵活性。

如果未指定模式,实现将应用于所有模式(M)。如果至少指定了一个模式,它将应用于模型中存在的所有模式和[Binary]。这样,使用默认模式Binary的编码应该始终有效。

有关如何配置模式的更多信息,请参阅[derives]。

以下是一个简单示例,展示如何使用两种模式为单个结构体提供两种完全不同的格式:

use musli::{Decode, Encode}; use musli::json::Encoding; enum Alt {} #[derive(Decode, Encode)] #[musli(mode = Alt, packed)] #[musli(name_all = "name")] struct Word<'a> { text: &'a str, teineigo: bool, } const CONFIG: Encoding = Encoding::new(); const ALT_CONFIG: Encoding<Alt> = Encoding::new().with_mode(); let word = Word { text: "あります", teineigo: true, }; let out = CONFIG.to_string(&word)?; assert_eq!(out, r#"{"text":"あります","teineigo":true}"#); let out = ALT_CONFIG.to_string(&word)?; assert_eq!(out, r#"["あります",true]"#);
<br>

不安全性

以下是本crate中使用不安全代码的非详尽列表及其原因:

  • Tag::kind中的mem::transmute。它确保转换为#[repr(u8)]Kind枚举尽可能高效。

  • 一个主要不安全的SliceReader,它提供比&[u8]的默认Reader实现更高效的读取。因为它可以直接在指针上执行大部分必要的比较。

  • musli::json中与UTF-8处理相关的一些不安全性,因为我们内部自己检查UTF-8有效性(类似serde_json)。

  • FixedBytes<N>是一个可以操作未初始化数据的基于栈的容器。它的实现大部分是不安全的。通过它可以执行基于栈的序列化,这在no-std环境中很有用。

  • 在所有二进制格式中,一些unsafe用于拥有所有权的String解码,以支持通过[simdutf8]进行更快的字符串处理。禁用simdutf8功能(默认启用)会移除这些不安全使用。

为确保这个库在内存安全方面的正确实现,使用miri进行了广泛的测试和模糊测试。更多信息请参见[tests]。

<br>

[此处省略了原文中的链接引用部分]

Footnotes

  1. 意味着 Müsli 应该能够满足您的所有需求,甚至更多。

  2. 这严格来说不是二进制序列化,但它是作为一个试金石来实现的,以确保 Müsli 具有支持它所需的必要框架功能。幸运的是,这个实现也相当不错!

编辑推荐精选

TRAE编程

TRAE编程

AI辅助编程,代码自动修复

Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。

热门AI工具生产力协作转型TraeAI IDE
蛙蛙写作

蛙蛙写作

AI小说写作助手,一站式润色、改写、扩写

蛙蛙写作—国内先进的AI写作平台,涵盖小说、学术、社交媒体等多场景。提供续写、改写、润色等功能,助力创作者高效优化写作流程。界面简洁,功能全面,适合各类写作者提升内容品质和工作效率。

AI助手AI工具AI写作工具AI辅助写作蛙蛙写作学术助手办公助手营销助手
问小白

问小白

全能AI智能助手,随时解答生活与工作的多样问题

问小白,由元石科技研发的AI智能助手,快速准确地解答各种生活和工作问题,包括但不限于搜索、规划和社交互动,帮助用户在日常生活中提高效率,轻松管理个人事务。

聊天机器人AI助手热门AI工具AI对话
Transly

Transly

实时语音翻译/同声传译工具

Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。

讯飞智文

讯飞智文

一键生成PPT和Word,让学习生活更轻松

讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。

热门AI工具AI办公办公工具讯飞智文AI在线生成PPTAI撰写助手多语种文档生成AI自动配图
讯飞星火

讯飞星火

深度推理能力全新升级,全面对标OpenAI o1

科大讯飞的星火大模型,支持语言理解、知识问答和文本创作等多功能,适用于多种文件和业务场景,提升办公和日常生活的效率。讯飞星火是一个提供丰富智能服务的平台,涵盖科技资讯、图像创作、写作辅助、编程解答、科研文献解读等功能,能为不同需求的用户提供便捷高效的帮助,助力用户轻松获取信息、解决问题,满足多样化使用场景。

模型训练热门AI工具内容创作智能问答AI开发讯飞星火大模型多语种支持智慧生活
Spark-TTS

Spark-TTS

一种基于大语言模型的高效单流解耦语音令牌文本到语音合成模型

Spark-TTS 是一个基于 PyTorch 的开源文本到语音合成项目,由多个知名机构联合参与。该项目提供了高效的 LLM(大语言模型)驱动的语音合成方案,支持语音克隆和语音创建功能,可通过命令行界面(CLI)和 Web UI 两种方式使用。用户可以根据需求调整语音的性别、音高、速度等参数,生成高质量的语音。该项目适用于多种场景,如有声读物制作、智能语音助手开发等。

咔片PPT

咔片PPT

AI助力,做PPT更简单!

咔片是一款轻量化在线演示设计工具,借助 AI 技术,实现从内容生成到智能设计的一站式 PPT 制作服务。支持多种文档格式导入生成 PPT,提供海量模板、智能美化、素材替换等功能,适用于销售、教师、学生等各类人群,能高效制作出高品质 PPT,满足不同场景演示需求。

讯飞绘文

讯飞绘文

选题、配图、成文,一站式创作,让内容运营更高效

讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。

AI助手热门AI工具AI创作AI辅助写作讯飞绘文内容运营个性化文章多平台分发
材料星

材料星

专业的AI公文写作平台,公文写作神器

AI 材料星,专业的 AI 公文写作辅助平台,为体制内工作人员提供高效的公文写作解决方案。拥有海量公文文库、9 大核心 AI 功能,支持 30 + 文稿类型生成,助力快速完成领导讲话、工作总结、述职报告等材料,提升办公效率,是体制打工人的得力写作神器。

下拉加载更多