2个版本

0.1.1 2024年6月27日
0.1.0 2024年6月26日

695嵌入式开发

每月下载 47

自定义许可证

14KB
118 代码行

fieldset

Maintenance CI docs

这个库将字段修改作为数据跟踪。它旨在提供一种有界空间的替代方案,用于事件监听器,特别适用于但不仅限于嵌入式系统的使用。

它通过从一个结构体派生出 FieldType、一个 FieldSetter 特性和多个 FieldSet 类型来实现。

  • FieldType 是一个枚举,其中每个变体对应于结构体的每个字段。
  • FieldSetter 特性由每个字段的设置方法组成。
  • FieldSet 类型实现了 FieldSetter 特性,并提供了一个迭代接口,其中每个项目都是一个与修改的字段对应的 FieldType 实例。

子系统可以使用 FieldSetter 接口来“修改”原始参数结构的字段,然后可以迭代 FieldSet 以通知其他子系统字段已被修改。这允许通过批量修改并在之后进行通知来实现事件驱动架构。

存在多个 FieldSetter 实现,它们在迭代和备份存储方面具有不同的权衡。

  • OptFieldSet 由派生结构体支持,其中每个字段都转换为 Option。每次迭代都会遍历所有字段,因此适用于较小的结构或频繁的修改。
  • BitFieldSet 由长度等于字段数的 FieldType 迭代数组和跟踪哪些字段已被修改的 bitfield 支持。迭代是最优的,并且仅遍历恰好与修改的字段一样多的字段。缺点是每个字段在迭代之前只能修改一次,并且后续的修改将被忽略。这通常是一个好的折衷方案。
  • PerfFieldSet 由长度等于字段数的 FieldType 数组和跟踪哪些字段已被修改及其在迭代数组中的当前位置的互补数组支持。迭代是最优的,并且仅遍历恰好与修改的字段一样多的字段。字段可以多次修改,并且只有最后一次修改生效。缺点是需要额外的空间来跟踪多次修改。

当前库需要使用 nightly 模式下的 impl_trait_in_assoc_type 功能。

示例

#![feature(impl_trait_in_assoc_type)]
use fieldset::{FieldSetter, FieldSet};

#[derive(Default, FieldSet)]
struct SubModel {
    a: f32,
    b: u32
}

#[derive(Default, FieldSet)]
struct DomainModel {
    #[fieldset]
    sub: SubModel,
    c: f32
}

fn sub_modifier(mut model: impl SubModelFieldSetter, i: u32) {
    model.b().set(i);
}

fn modifier(mut model: impl DomainModelFieldSetter, i: u32) {
    model.c().set(i as f32);
    sub_modifier(model.sub(), i);
}

fn example() {
    let mut model = DomainModel::default();
    for i in 0..10 {
        let mut field_set = DomainModelPerfFieldSet::default();
        modifier(&mut field_set, i);
        let mut iter = field_set.into_iter();
        for field_change in iter.clone() {
            model.apply(field_change);
        }
        assert_eq!(iter.next(), Some(DomainModelFieldType::C(i as f32)));
        assert_eq!(iter.next(), Some(DomainModelFieldType::Sub(SubModelFieldType::B(i))));
        assert_eq!(model.c, i as f32);
        assert_eq!(model.sub.b, i);
    }
}

依赖项

~0.9–1.4MB
~26K SLoC