#枚举 #变体 #计数器 #派生 #记录 #方法 #

no-std variant_counter

Rust 的枚举变体计数器

6 个版本 (3 个重大更新)

0.4.0 2021 年 9 月 15 日
0.3.0 2021 年 8 月 16 日
0.2.2 2021 年 8 月 13 日
0.1.0 2021 年 8 月 11 日

1353Rust 模式

每月 25 次下载

MIT 许可证

17KB
57

variant-counter

Crates.io docs.rs

用于计算 Rust 枚举变体的高效且优雅的库。

开始使用

#[派生(VariantCount)]

#[derive(VariantCount)]
pub enum Enum {
    Variant1,
    Variant2,
}

记录变体

let mut counter = Enum::counter();
counter.record(&Enum::Variant1);

使用 erase_*() 方法擦除记录

counter.erase_variant1();

这些 erase_*() 方法在 erase 功能标志下,默认禁用。

使用 check_*() 方法检查记录

assert_eq!(counter.check_variant1(), 1);

这些 check_*() 方法在 check 功能标志下,默认禁用。

使用 discard()reset() 数据

// Clear the `Enum::Variant1`'s data.
counter.discard(&Enum::Variant1);

// Clear all variants data.
counter.reset();

忽略变体

#[derive(VariantCount)]
pub enum Level {
    #[counter(ignore)]
    Trace,
    Debug,
    Info,
    Warn,
    Error,
}

如果忽略了一个变体,在记录该变体时将没有任何影响。

let mut counter = Level::counter();
// Record nothing...
counter.record(&Level::Trace);

聚合数据

let data = counter.aggregate();

分组变体

#[derive(VariantCount)]
pub enum Platform {
    #[counter(group = "Mobile")]
    Android,
    #[counter(group = "Mobile")]
    IOS,
    #[counter(group = "Desktop")]
    Windows,
    #[counter(group = "Desktop")]
    Linux,
    #[counter(group = "Desktop")]
    MacOS,
    #[counter(group = "Desktop")]
    ChromeOS,
    Others,
}

let counter = Platform::counter();
// Group version of aggregate method
let group_data = counter.group_aggregate();

统计信息

// Sum
counter.sum();

// Average
counter.avg();

// Variance
counter.variance();

// Standard deviation
counter.sd();

加权

#[derive(VariantCount)]
enum Rating {
    #[counter(weight = 1)]
    Hated,
    #[counter(weight = 2)]
    Disliked,
    #[counter(weight = 3)]
    Ok,
    #[counter(weight = 4)]
    Liked,
    #[counter(weight = 5)]
    Loved,
}

let mut counter = Rating::counter();
counter.record(&Rating::Loved);

let w = counter.weighted();

// Sum
w.sum();

// Average
w.avg();

// Variance
w.variance();

// Standard deviation
w.sd();

宏展开

您可以使用 carg-expand 展开派生的 VariantCount 宏。以下是展开的代码

enum Enum {
    Variant1,
    Variant2,
}
impl Enum {
    #[inline]
    const fn variant_count() -> usize {
        2usize
    }
}
impl variant_counter::VariantCount for Enum {
    type Counter = EnumCounter;
    fn counter() -> Self::Counter {
        EnumCounter::new()
    }
}
/// The concrete counter struct auto-generated by macro.
#[must_use]
struct EnumCounter {
    /// An array store the frequency of each variant which not be ignored.
    frequency: [usize; 2usize],
}
impl EnumCounter {
    const fn new() -> EnumCounter {
        EnumCounter {
            frequency: [0; 2usize],
        }
    }
    /// Record a variant. It has no effect if you record an ignored variant.
    fn record(&mut self, target: &Enum) {
        let pair = match target {
            Enum::Variant1 => Some(0usize),
            Enum::Variant2 => Some(1usize),
            _ => None,
        };
        if let Some(index) = pair {
            self.frequency[index] = self.frequency[index].saturating_add(1);
        }
    }
    /// Discard the record of the target variant.
    /// It has no effect if you discard an ignored variant.
    fn discard(&mut self, target: &Enum) {
        let index = match target {
            Enum::Variant1 => Some(0usize),
            Enum::Variant2 => Some(1usize),
            _ => None,
        };
        if let Some(index) = index {
            self.frequency[index] = 0;
        }
    }
    /// Reset the records.
    fn reset(&mut self) {
        self.frequency = [0; 2usize];
    }
    /// Aggregate the data to a HashMap.
    #[cfg(feature = "std")]
    fn aggregate(&self) -> std::collections::HashMap<&'static str, usize> {
        IntoIterator::into_iter([
            ("Variant1", self.frequency[0usize]),
            ("Variant2", self.frequency[1usize]),
        ])
        .collect()
    }
    /// Get the sum of frequency.
    #[inline]
    fn sum(&self) -> usize {
        self.frequency.iter().sum()
    }
}

功能标志

  • full:启用所有功能。

  • check:为变体生成 check 方法。

  • erase:为变体生成 erase 方法。

  • stats:生成统计方法,如 avg()variance()sd() 等。

  • std:启用 std 包支持。默认启用。请禁用此功能以支持 no_std

依赖关系

~1.5MB
~35K SLoC