Rust版本控制与代码生成库revision-derive的使用:简化版本管理并自动化生成修订代码

revision-derive

revision的过程宏私有实现。

status docs.rs Crates.io license

元数据

包标识符: pkg:cargo/revision-derive@0.12.0

更新时间: 3个月前

版本: 2021 edition

许可证: Apache-2.0

大小: 15.8 KiB

安装

在项目目录中运行以下Cargo命令:

cargo add revision-derive

或者在Cargo.toml中添加以下行:

revision-derive = "0.12.0"

文档

docs.rs/revision-derive/0.12.0

仓库

github.com/surrealdb/revision

所有者

  • Tobie Morgan Hitchcock

分类

  • Encoding

完整示例代码

use revision::revision;
use revision_derive::Revision;
use serde::{Deserialize, Serialize};

// 定义一个带有版本控制的结构体
#[derive(Debug, Clone, Serialize, Deserialize, Revision)]
#[revision = "v1"] // 初始版本
struct User {
    id: u64,
    name: String,
    email: String,
}

impl User {
    // 创建新用户
    fn new(id: u64, name: String, email: String) -> Self {
        Self { id, name, email }
    }
}

fn main() {
    // 创建用户实例
    let user = User::new(1, "Alice".to_string(), "alice@example.com".to_string());
    
    println!("User: {:?}", user);
    println!("Revision: {}", user.revision());
    
    // 序列化示例
    let serialized = serde_json::to_string(&user).unwrap();
    println!("Serialized: {}", serialized);
    
    // 反序列化示例
    let deserialized: User = serde_json::from_str(&serialized).unwrap();
    println!("Deserialized: {:?}", deserialized);
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_user_creation() {
        let user = User::new(1, "Test".to_string(), "test@example.com".to_string());
        assert_eq!(user.id, 1);
        assert_eq!(user.name, "Test");
        assert_eq!(user.email, "test@example.com");
    }

    #[test]
    fn test_revision() {
        let user = User::new(1, "Test".to_string(), "test@example.com".to_string());
        assert_eq!(user.revision(), "v1");
    }
}

Cargo.toml 依赖配置:

[dependencies]
revision = "0.12.0"
revision-derive = "0.12.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

1 回复

Rust版本控制与代码生成库revision-derive使用指南

概述

revision-derive是一个用于简化Rust代码版本管理的派生宏库,通过自动化生成修订代码来帮助开发者管理数据结构的不同版本。

主要功能

  • 自动生成版本控制相关代码
  • 支持数据结构的多版本序列化/反序列化
  • 提供版本迁移和兼容性处理

安装方法

在Cargo.toml中添加依赖:

[dependencies]
revision-derive = "0.1"
serde = { version = "1.0", features = ["derive"] }

基本用法示例

use revision_derive::Revisioned;
use serde::{Deserialize, Serialize};

#[derive(Revisioned, Serialize, Deserialize, Debug)]
#[revision(version = 1)]
struct User {
    id: u64,
    name: String,
    #[revision(version = 2)]
    email: Option<String>,
    #[revision(version = 3)]
    age: u32,
}

fn main() {
    // 自动生成的版本信息
    println!("Current version: {}", User::current_version());
    
    // 序列化示例
    let user = User {
        id: 1,
        name: "Alice".to_string(),
        email: Some("alice@example.com".to_string()),
        age: 25,
    };
    
    let bytes = user.to_bytes().unwrap();
    
    // 反序列化示例(自动处理版本兼容)
    let decoded: User = User::from_bytes(&bytes).unwrap();
    println!("Decoded user: {:?}", decoded);
}

高级功能

自定义版本迁移

#[derive(Revisioned)]
#[revision(version = 2)]
struct Product {
    name: String,
    #[revision(version = 1, rename = "old_price")]
    price: f64,
    #[revision(version = 2)]
    category: String,
    
    #[revision_migration(from = 1)]
    fn migrate_v1_to_v2(old: &[u8]) -> Result<Self, RevisionError> {
        // 自定义迁移逻辑
        Ok(Product {
            name: "Migrated".to_string(),
            price: 0.0,
            category: "Default".to_string(),
        })
    }
}

版本范围支持

#[derive(Revisioned)]
struct Config {
    #[revision(start = 1, end = 3)]
    old_setting: String,
    
    #[revision(start = 2)]
    new_setting: i32,
}

特性说明

  1. 自动版本检测:根据字段注解自动确定数据结构版本
  2. 向后兼容:支持旧版本数据的自动转换
  3. 灵活配置:支持版本范围、重命名等高级功能
  4. 错误处理:提供详细的版本迁移错误信息

注意事项

  • 确保所有修订版本的字段都有合理的默认值或迁移逻辑
  • 版本号应该单调递增
  • 测试所有版本迁移路径以确保兼容性

这个库特别适合需要长期维护和演进的数据结构,特别是在需要保持向后兼容性的分布式系统或持久化存储场景中。

完整示例demo

use revision_derive::Revisioned;
use serde::{Deserialize, Serialize};
use std::fmt;

// 定义错误类型
#[derive(Debug)]
pub enum RevisionError {
    MigrationError(String),
    SerializationError(String),
    DeserializationError(String),
}

impl fmt::Display for RevisionError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            RevisionError::MigrationError(msg) => write!(f, "Migration error: {}", msg),
            RevisionError::SerializationError(msg) => write!(f, "Serialization error: {}", msg),
            RevisionError::DeserializationError(msg) => write!(f, "Deserialization error: {}", msg),
        }
    }
}

impl std::error::Error for RevisionError {}

// 用户数据结构示例
#[derive(Revisioned, Serialize, Deserialize, Debug, PartialEq)]
#[revision(version = 1)]
struct User {
    id: u64,                    // 从版本1开始存在
    name: String,               // 从版本1开始存在
    #[revision(version = 2)]    // 从版本2开始添加
    email: Option<String>,
    #[revision(version = 3)]    // 从版本3开始添加
    age: u32,
}

// 产品数据结构示例(带自定义迁移)
#[derive(Revisioned, Debug, PartialEq)]
#[revision(version = 2)]
struct Product {
    name: String,
    #[revision(version = 1, rename = "old_price")]  // 版本1中名为old_price
    price: f64,
    #[revision(version = 2)]    // 从版本2开始添加
    category: String,
    
    #[revision_migration(from = 1)]
    fn migrate_v1_to_v2(old_data: &[u8]) -> Result<Self, RevisionError> {
        // 模拟从版本1迁移到版本2的逻辑
        // 在实际应用中,这里会解析旧版本数据并转换为新版本
        println!("Migrating from version 1 to version 2...");
        
        Ok(Product {
            name: "Migrated Product".to_string(),
            price: 99.99,
            category: "Electronics".to_string(),
        })
    }
}

// 配置数据结构示例(版本范围支持)
#[derive(Revisioned, Debug, PartialEq)]
struct Config {
    #[revision(start = 1, end = 3)]  // 只在版本1-3中存在
    old_setting: String,
    
    #[revision(start = 2)]           // 从版本2开始存在
    new_setting: i32,
}

fn main() -> Result<(), RevisionError> {
    println!("=== User 示例 ===");
    
    // 创建用户实例
    let user = User {
        id: 1,
        name: "Alice".to_string(),
        email: Some("alice@example.com".to_string()),
        age: 25,
    };
    
    // 显示当前版本
    println!("Current User version: {}", User::current_version());
    println!("Original user: {:?}", user);
    
    // 序列化
    let bytes = user.to_bytes().map_err(|e| RevisionError::SerializationError(e.to_string()))?;
    println!("Serialized bytes length: {}", bytes.len());
    
    // 反序列化
    let decoded: User = User::from_bytes(&bytes).map_err(|e| RevisionError::DeserializationError(e.to_string()))?;
    println!("Decoded user: {:?}", decoded);
    println!("Users are equal: {}", user == decoded);
    
    println!("\n=== Product 示例 ===");
    
    // 产品示例
    let product = Product {
        name: "Laptop".to_string(),
        price: 1299.99,
        category: "Computers".to_string(),
    };
    
    println!("Current Product version: {}", Product::current_version());
    println!("Product: {:?}", product);
    
    println!("\n=== Config 示例 ===");
    
    // 配置示例
    let config = Config {
        old_setting: "old_value".to_string(),
        new_setting: 42,
    };
    
    println!("Config: {:?}", config);
    
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_user_serialization() {
        let user = User {
            id: 1,
            name: "Test".to_string(),
            email: Some("test@example.com".to_string()),
            age: 30,
        };
        
        let bytes = user.to_bytes().unwrap();
        let decoded: User = User::from_bytes(&bytes).unwrap();
        
        assert_eq!(user, decoded);
    }
    
    #[test]
    fn test_version_info() {
        assert_eq!(User::current_version(), 3);
        assert_eq!(Product::current_version(), 2);
    }
}

这个完整示例展示了revision-derive库的主要功能:

  1. 基本用法:User结构体展示了版本控制的基本用法,包含不同版本添加的字段
  2. 自定义迁移:Product结构体演示了如何实现自定义版本迁移逻辑
  3. 版本范围:Config结构体展示了版本范围的使用
  4. 错误处理:包含了完整的错误处理机制
  5. 测试用例:提供了基本的测试示例

要运行此示例,请确保在Cargo.toml中添加了正确的依赖项,并根据需要调整版本号。

回到顶部