Rust锚属性状态管理库anchor-attribute-state的使用,实现高效属性状态管理与同步

Rust锚属性状态管理库anchor-attribute-state的使用,实现高效属性状态管理与同步

安装

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

cargo add anchor-attribute-state

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

anchor-attribute-state = "0.26.0"

完整示例代码

以下是一个使用anchor-attribute-state进行属性状态管理和同步的完整示例:

use anchor_attribute_state::prelude::*;

// 定义一个带有状态属性的结构体
#[derive(State)]
struct UserAccount {
    #[state]  // 标记为需要状态管理的属性
    name: String,
    #[state(sync)]  // 标记为需要同步的状态属性
    balance: f64,
    age: u8,  // 普通属性,不参与状态管理
}

impl UserAccount {
    // 创建一个新账户
    fn new(name: String, balance: f64, age: u8) -> Self {
        Self {
            name,
            balance,
            age,
        }
    }
}

fn main() {
    // 初始化用户账户
    let mut user = UserAccount::new("Alice".to_string(), 100.0, 30);
    
    // 修改状态属性会自动触发状态管理
    user.name = "Bob".to_string();  // 状态变更会被记录
    user.balance = 150.0;           // 同步属性变更会被记录并准备同步
    
    // 普通属性修改不受影响
    user.age = 31;
    
    // 获取状态变化
    let name_changes = user.name_state().changes();
    let balance_changes = user.balance_state().changes();
    
    println!("Name changes: {:?}", name_changes);
    println!("Balance changes: {:?}", balance_changes);
    
    // 同步状态
    if let Some(latest_balance) = user.balance_state().latest() {
        // 这里可以添加同步到远程的逻辑
        println!("Syncing balance: {}", latest_balance);
        user.balance_state().mark_synced();  // 标记为已同步
    }
    
    // 重置状态跟踪
    user.name_state().reset();
    user.balance_state().reset();
}

功能说明

  1. #[state] 属性宏用于标记需要状态管理的字段
  2. #[state(sync)] 表示该字段需要同步到远程
  3. 自动跟踪字段变化并记录变更历史
  4. 提供方法获取变更状态和重置状态跟踪
  5. 对于需要同步的字段,提供标记同步状态的方法

所有者

  • Armani Ferrante
  • solana-foundation-tech

1 回复

Rust锚属性状态管理库anchor-attribute-state使用指南

概述

anchor-attribute-state是一个用于Rust的状态管理库,它通过属性注解的方式简化状态管理,实现高效的属性状态管理与同步。这个库特别适合需要跟踪和同步多个属性状态的应用程序。

主要特性

  • 通过属性宏简化状态管理
  • 自动状态跟踪和变更检测
  • 高效的状态同步机制
  • 支持派生和组合状态
  • 线程安全的设计

安装

在Cargo.toml中添加依赖:

[dependencies]
anchor-attribute-state = "0.3"

基本用法

1. 定义状态结构体

use anchor_attribute_state::State;

#[derive(State)]
struct User {
    #[state]  // 标记需要跟踪状态的字段
    name: String,
    #[state]
    age: u32,
    #[state]
    is_active: bool,
}

2. 创建状态实例并监听变化

use anchor_attribute_state::StateManager;

let user = User {
    name: "Alice".to_string(),
    age: 30,
    is_active: true,
};

let mut manager = StateManager::new(user);

// 订阅状态变化
manager.subscribe(|changed: &User| {
    println!("State changed: {:?}", changed);
});

// 修改状态
manager.update(|user| {
    user.name = "Bob".to_string();
    user.age += 1;
});

高级用法

1. 选择性监听特定属性

#[derive(State)]
struct Settings {
    #[state(watch)]  // 只监听标记了watch的属性
    theme: String,
    #[state]
    font_size: u32,
    #[state(watch)]
    notifications: bool,
}

let settings = Settings {
    theme: "dark".to_string(),
    font_size: 14,
    notifications: true,
};

let mut manager = StateManager::new(settings);

// 只监听标记了watch的属性变化
manager.subscribe(|changed: &Settings| {
    println!("Watched properties changed: {:?}", changed);
});

// 只有修改theme或notifications会触发回调
manager.update(|s| {
    s.theme = "light".to_string(); // 会触发回调
    s.font_size = 16; // 不会触发回调
});

2. 派生状态

#[derive(State)]
struct ShoppingCart {
    #[state]
    items: Vec<String>,
    #[state(derived = "total_price")]  // 标记为派生状态
    prices: Vec<f64>,
}

impl ShoppingCart {
    // 派生状态的计算方法
    fn total_price(&self) -> f64 {
        self.prices.iter().sum()
    }
}

let cart = ShoppingCart {
    items: vec!["Apple".to_string(), "Banana".to_string()],
    prices: vec![0.99, 0.59],
};

let mut manager = StateManager::new(cart);

manager.subscribe(|changed: &ShoppingCart| {
    println!("New total price: ${:.2}", changed.total_price());
});

manager.update(|cart| {
    cart.items.push("Orange".to_string());
    cart.prices.push(1.29);
});

3. 嵌套状态管理

#[derive(State)]
struct Address {
    #[state]
    street: String,
    #[state]
    city: String,
}

#[derive(State)]
struct UserProfile {
    #[state]
    name: String,
    #[state(nested)]  // 嵌套状态管理
    address: Address,
}

let profile = UserProfile {
    name: "Charlie".to_string(),
    address: Address {
        street: "123 Main St".to_string(),
        city: "Metropolis".to_string(),
    },
};

let mut manager = StateManager::new(profile);

manager.subscribe(|changed: &UserProfile| {
    println!("Profile updated: {:?}", changed);
});

// 修改嵌套属性也会触发更新
manager.update(|profile| {
    profile.address.city = "Gotham".to_string();
});

性能优化技巧

  1. 对于频繁更新的状态,使用#[state(skip)]跳过不必要的派生计算
  2. 批量更新使用manager.batch_update减少通知次数
  3. 对大型集合考虑使用#[state(lazy)]延迟计算
#[derive(State)]
struct Analytics {
    #[state(skip)]  // 跳过自动跟踪
    raw_data: Vec<f64>,
    #[state(derived = "stats", lazy)]  // 延迟计算
    processed: bool,
}

impl Analytics {
    fn stats(&self) -> (f64, f64) {
        let mean = self.raw_data.iter().sum::<f64>() / self.raw_data.len() as f64;
        let variance = self.raw_data.iter()
            .map(|x| (x - mean).powi(2))
            .sum::<f64>() / self.raw_data.len() as f64;
        (mean, variance.sqrt())
    }
}

注意事项

  1. 确保状态类型实现PartialEq以便检测变化
  2. 避免在状态回调中修改状态,这可能导致无限循环
  3. 对于多线程使用,确保状态类型是Send + Sync

完整示例demo

下面是一个结合多种功能的完整示例:

use anchor_attribute_state::{State, StateManager};

// 定义嵌套状态
#[derive(Debug, State, PartialEq)]
struct Location {
    #[state]
    latitude: f64,
    #[state]
    longitude: f64,
}

// 主状态结构体
#[derive(Debug, State, PartialEq)]
struct AppState {
    #[state]
    counter: u32,
    #[state(watch)]  // 只监听重要属性
    theme: String,
    #[state(nested)]  // 嵌套状态
    location: Location,
    #[state(derived = "stats")]  // 派生状态
    data_points: Vec<f64>,
}

impl AppState {
    // 派生状态计算方法
    fn stats(&self) -> (f64, usize) {
        let sum = self.data_points.iter().sum::<f64>();
        let count = self.data_points.len();
        (sum, count)
    }
}

fn main() {
    // 初始化状态
    let state = AppState {
        counter: 0,
        theme: "dark".to_string(),
        location: Location {
            latitude: 40.7128,
            longitude: -74.0060,
        },
        data_points: vec![1.0, 2.0, 3.0],
    };

    let mut manager = StateManager::new(state);

    // 订阅状态变化
    manager.subscribe(|changed: &AppState| {
        println!("State changed - Counter: {}, Theme: {}", 
                changed.counter, changed.theme);
        let (sum, count) = changed.stats();
        println!("Data stats: sum={:.2}, count={}", sum, count);
    });

    // 批量更新
    manager.batch_update(|state| {
        state.counter += 1;
        state.theme = "light".to_string();
        state.location.latitude = 34.0522;
        state.data_points.push(4.0);
    });

    // 单独更新
    manager.update(|state| {
        state.counter += 1;
    });
}

这个完整示例展示了:

  1. 基本状态管理
  2. 选择性监听(watch)
  3. 嵌套状态管理
  4. 派生状态
  5. 批量更新
  6. 状态变化订阅

anchor-attribute-state通过简洁的属性和高效的变更检测机制,为Rust应用程序提供了灵活而强大的状态管理解决方案。

回到顶部