The efficient and elegant crate to count variants of Rust's Enum.
#[derive(VariantCount)]
```rust
pub enum Enum { Variant1, Variant2, } ```
rust
let mut counter = Enum::counter();
counter.record(&Enum::Variant1);
erase_*()
methodsrust
counter.erase_variant1();
Those erase_*()
methods are under erase
feature flag, and disabled by default.
check_*()
methodsrust
assert_eq!(counter.check_variant1(), 1);
Those check_*()
methods are under check
feature flag, and disabled by default.
discard()
, or reset()
the data``rust
// Clear the
Enum::Variant1`'s data.
counter.discard(&Enum::Variant1);
// Clear all variants data. counter.reset(); ```
```rust
pub enum Level { #[counter(ignore)] Trace, Debug, Info, Warn, Error, } ```
If a variant was ignored, it has no effect when you record that variant.
```rust let mut counter = Level::counter(); // Record nothing... counter.record(&Level::Trace);
```
rust
let data = counter.aggregate();
```rust
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 groupdata = counter.groupaggregate(); ```
```rust // Sum counter.sum();
// Average counter.avg();
// Variance counter.variance();
// Standard deviation counter.sd(); ```
```rust
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(); ```
You can use carg-expand to expand the derived VariantCount
macro.
Here is the expanded code:
```rust enum Enum { Variant1, Variant2, } impl Enum { #[inline] const fn variantcount() -> usize { 2usize } } impl variantcounter::VariantCount for Enum { type Counter = EnumCounter; fn counter() -> Self::Counter { EnumCounter::new() } } /// The concrete counter struct auto-generated by macro.
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].saturatingadd(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::intoiter([ ("Variant1", self.frequency[0usize]), ("Variant2", self.frequency[1usize]), ]) .collect() } /// Get the sum of frequency. #[inline] fn sum(&self) -> usize { self.frequency.iter().sum() } } ```
full
: Enable all features.
check
: Generate check
methods for variants.
erase
: Generate erase
methods for variants.
stats
: Generate statistics methods, such as avg()
, variance()
, and sd()
, etc.
std
: Enable std
crate supported. Enabled by default. Please disable this feature to support no_std
.