Rust序列化库musli的使用,musli提供高效灵活的数据序列化与反序列化功能

Rust序列化库musli的使用,musli提供高效灵活的数据序列化与反序列化功能

musli是一个灵活、快速且通用的Rust二进制序列化框架,性能优异且不妥协!它提供了一系列格式,每种格式都有其文档完善的功能和权衡。

概述

  • 使用derives模块学习如何实现EncodeDecode特性
  • 查看data_model了解Müsli的抽象数据模型
  • 查看基准测试和大小比较了解框架性能
  • 无缝兼容serde,可通过musli::serde模块实现

使用

Cargo.toml中添加以下内容(根据你选择的格式):

[dependencies]
musli = { version = "0.0.131", features = ["storage"] }

设计

核心功能由EncodeDecode派生宏实现,这些宏在derives模块中有详细文档。

use musli::{Encode, Decode};

#[derive(Encode, Decode)]
struct Person {
    /* .. fields .. */
}

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

完整示例

以下是一个完整的musli使用示例,展示如何序列化和反序列化数据:

use musli::{Encode, Decode};
use musli::storage::Encoding;

#[derive(Debug, Encode, Decode)]
struct Person {
    name: String,
    age: u32,
    #[musli(default)]
    address: Option<String>,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建编码实例
    let encoding = Encoding::new();
    
    // 创建示例数据
    let person = Person {
        name: "Alice".to_string(),
        age: 30,
        address: Some("123 Main St".to_string()),
    };
    
    // 序列化
    let bytes = encoding.to_vec(&person)?;
    println!("Serialized: {:?}", bytes);
    
    // 反序列化
    let decoded: Person = encoding.from_slice(&bytes)?;
    println!("Deserialized: {:?}", decoded);
    
    Ok(())
}

升级稳定性

musli支持不同级别的升级稳定性。以下示例展示完全升级稳定性:

use musli::{Encode, Decode};

#[derive(Debug, PartialEq, Encode, Decode)]
struct Version1 {
    #[musli(Binary, name = 0)]
    name: String,
}

#[derive(Debug, PartialEq, Encode, Decode)]
struct Version2 {
    #[musli(Binary, name = 0)]
    name: String,
    #[musli(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中,同一个模型可以通过不同的模式进行序列化:

use musli::{Decode, Encode};
use musli::json::Encoding;

enum Alt {}

#[derive(Decode, Encode)]
#[musli(Text, name_all = "name")]
#[musli(mode = Alt, packed)]
struct Word<'a> {
    text: &'a str,
    teineigo: bool,
}

const TEXT: Encoding = Encoding::new();
const ALT: Encoding<Alt> = Encoding::new().with_mode();

let word = Word {
    text: "あります",
    teineigo: true,
};

let out = TEXT.to_string(&word)?;
assert_eq!(out, r#"{"text":"あります","teineigo":true}"#);

let out = ALT.to_string(&word)?;
assert_eq!(out, r#"["あります",true]"#);

性能优化

为了实现最高性能,可以使用以下优化方法:

use musli::alloc::{Allocator, System};
use musli::context::{self, ErrorMarker as Error};
use musli::options::{self, Float, Integer, Width, Options};
use musli::storage::Encoding;
use musli::{Decode, Encode};
use musli::alloc::Slice;

enum Packed {}

const OPTIONS: Options = options::new().fixed().native_byte_order().build();
const ENCODING: Encoding<OPTIONS, Packed> = Encoding::new().with_options().with_mode();

#[inline]
pub fn encode<'buf, T, A>(buf: &'buf mut [u8], value: &T, alloc: A) -> Result<&'buf [u8], Error>
where
    T: Encode<Packed>,
    A: Allocator,
{
    let cx = context::new_in(alloc);
    let w = ENCODING.to_slice_with(&cx, &mut buf[..], value)?;
    Ok(&buf[..w])
}

#[inline]
pub fn decode<'buf, T, A](buf: &'buf [u8], alloc: A) -> Result<T, Error>
where
    T: Decode<'buf, Packed, A>,
    A: Allocator,
{
    let cx = context::new_in(alloc);
    ENCODING.from_slice_with(&cx, buf)
}

与serde的区别

  • Müsli的数据模型不与Rust绑定
  • 使用GATs提供更易用的抽象
  • 所有东西都是DecoderEncoder
  • 只在需要时使用访问者模式
  • 发明了模式编码
  • 完全支持no-std和no-alloc
  • 提供详细的解码跟踪

格式

musli提供的格式及其能力:

格式 重新排序 缺失字段 未知字段 自描述
musli::packed
musli::storage
musli::wire
musli::descriptive
musli::json

完整示例demo

以下是一个更完整的musli使用示例,展示如何配置和使用不同的序列化模式:

use musli::{Encode, Decode};
use musli::json::Encoding;
use serde::{Serialize, Deserialize};

// 定义一个支持多种序列化模式的结构体
#[derive(Debug, PartialEq, Encode, Decode, Serialize, Deserialize)]
#[musli(name_all = "kebab-case")]
struct User {
    id: u64,
    username: String,
    #[musli(default)]
    #[serde(default)]
    email: Option<String>,
    is_active: bool,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建JSON编码实例
    let json_encoding = Encoding::new();
    
    // 创建用户数据
    let user = User {
        id: 42,
        username: "john_doe".to_string(),
        email: Some("john@example.com".to_string()),
        is_active: true,
    };
    
    // 序列化为JSON
    let json = json_encoding.to_string(&user)?;
    println!("Serialized JSON: {}", json);
    
    // 从JSON反序列化
    let decoded: User = json_encoding.from_str(&json)?;
    println!("Deserialized: {:?}", decoded);
    
    // 测试与serde的兼容性
    let serde_json = serde_json::to_string(&user)?;
    println!("Serde JSON: {}", serde_json);
    
    let musli_from_serde: User = json_encoding.from_str(&serde_json)?;
    println!("Musli from serde: {:?}", musli_from_serde);
    
    Ok(())
}

这个示例展示了:

  1. 使用musli进行JSON序列化和反序列化
  2. 结构体字段的默认值处理
  3. 字段命名策略配置
  4. 与serde的互操作性
  5. 完整的错误处理

musli是一个强大的序列化框架,提供了丰富的功能和灵活的配置选项,能够满足各种序列化需求。


1 回复

Rust序列化库musli的使用指南

介绍

musli是一个Rust数据序列化库,旨在提供高效且灵活的数据序列化与反序列化功能。它具有以下特点:

  • 高性能:musli设计时就考虑了性能优化
  • 灵活性:支持多种编码格式和配置选项
  • 零拷贝:支持零拷贝反序列化
  • 可扩展:允许自定义序列化逻辑

基本使用方法

添加依赖

首先在Cargo.toml中添加musli依赖:

[dependencies]
musli = "0.0"
musli-derive = "0.0"

基本序列化/反序列化

use musli::{Encode, Decode};

#[derive(Debug, PartialEq, Encode, Decode)]
struct Person {
    name: String,
    age: u32,
    hobbies: Vec<String>,
}

fn main() {
    let person = Person {
        name: "Alice".to_string(),
        age: 30,
        hobbies: vec!["reading".to_string(), "hiking".to_string()],
    };

    // 序列化为字节
    let bytes = musli::storage::to_vec(&person).unwrap();
    
    // 反序列化
    let decoded: Person = musli::storage::from_slice(&bytes).unwrap();
    
    assert_eq!(person, decoded);
}

高级功能

自定义编码格式

musli支持多种编码格式,例如JSON:

use musli_json::{Json, Buffer};

#[derive(Debug, PartialEq, Encode, Decode)]
struct Book {
    title: String,
    author: String,
    pages: u32,
}

fn main() {
    let book = Book {
        title: "Rust Programming".to_string(),
        author: "Jane Doe".to_string(),
        pages: 320,
    };

    let mut buffer = Buffer::new();
    let json = Json::new();
    
    // 序列化为JSON
    json.encode(&mut buffer, &book).unwrap();
    let json_str = buffer.as_str().unwrap();
    
    println!("Serialized JSON: {}", json_str);
    
    // 反序列化
    let decoded: Book = json.decode(json_str.as_bytes()).unwrap();
    assert_eq!(book, decoded);
}

零拷贝反序列化

use musli::{Decode, Mode};
use musli_json::Json;

#[derive(Debug, PartialEq, Decode)]
struct User<'a> {
    username: &'a str,
    email: &'a str,
}

fn main() {
    let json = r#"{"username":"alice","email":"alice@example.com"}"#;
    
    let user: User = Json::new().decode(json.as_bytes()).unwrap();
    
    println!("User: {:?}", user);
    // 注意:user中的字符串借用自原始JSON数据
}

字段属性控制

use musli::{Encode, Decode};

#[derive(Debug, Encode, Decode)]
struct Config {
    #[musli(rename = "server_address")]
    address: String,
    
    #[musli(skip)]
    internal_id: u64,
    
    #[musli(default)]
    timeout: Option<u32>,
}

性能建议

  1. 对于高性能场景,考虑使用musli::storage模块的二进制格式
  2. 对于需要互操作的场景,使用JSON或其他文本格式
  3. 尽可能使用零拷贝反序列化来减少内存分配

错误处理

musli提供了详细的错误信息:

use musli::Error;

fn deserialize_data(bytes: &[u8]) -> Result<Person, Error> {
    musli::storage::from_slice(bytes)
}

match deserialize_data(invalid_data) {
    Ok(person) => println!("Got person: {:?}", person),
    Err(e) => eprintln!("Deserialization failed: {}", e),
}

musli是一个功能强大且灵活的序列化库,特别适合需要高性能或特殊序列化需求的Rust项目。

完整示例demo

下面是一个结合了musli多种特性的完整示例:

use musli::{Encode, Decode};
use musli_json::{Json, Buffer};
use musli::Error;

// 定义一个包含多种特性的结构体
#[derive(Debug, PartialEq, Encode, Decode)]
struct Employee<'a> {
    #[musli(rename = "emp_name")]
    name: String,
    
    #[musli(default)]
    department: Option<String>,
    
    #[musli(skip)]
    internal_code: u32,
    
    contact: Contact<'a>,
    
    #[musli(rename = "work_years")]
    experience: u8,
}

// 零拷贝反序列化支持的结构体
#[derive(Debug, PartialEq, Encode, Decode)]
struct Contact<'a> {
    email: &'a str,
    phone: &'a str,
}

fn main() -> Result<(), Error> {
    // 准备JSON数据
    let json_data = r#"{
        "emp_name": "Bob Smith",
        "department": "Engineering",
        "contact": {
            "email": "bob@example.com",
            "phone": "123-456-7890"
        },
        "work_years": 5
    }"#;
    
    // 创建JSON编解码器
    let json = Json::new();
    
    // 反序列化 - 使用零拷贝
    let employee: Employee = json.decode(json_data.as_bytes())?;
    println!("Deserialized employee: {:?}", employee);
    
    // 修改数据
    let mut modified = employee;
    modified.experience += 1;
    modified.department = Some("Senior Engineering".to_string());
    
    // 序列化回JSON
    let mut buffer = Buffer::new();
    json.encode(&mut buffer, &modified)?;
    let new_json = buffer.as_str()?;
    
    println!("Serialized JSON:\n{}", new_json);
    
    Ok(())
}

这个完整示例展示了:

  1. 结构体字段的属性控制(rename, skip, default)
  2. 嵌套结构的处理
  3. 零拷贝反序列化
  4. JSON格式的序列化和反序列化
  5. musli的错误处理
  6. 完整的数据修改和重新序列化流程
回到顶部