Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/folyd/variant-counter
Rust's Enum variant counter
https://github.com/folyd/variant-counter
Last synced: about 2 months ago
JSON representation
Rust's Enum variant counter
- Host: GitHub
- URL: https://github.com/folyd/variant-counter
- Owner: Folyd
- License: mit
- Created: 2021-08-11T09:08:42.000Z (over 3 years ago)
- Default Branch: master
- Last Pushed: 2021-09-15T08:44:33.000Z (over 3 years ago)
- Last Synced: 2024-10-13T13:25:34.873Z (2 months ago)
- Language: Rust
- Homepage: https://crates.io/crates/variant_counter
- Size: 137 KB
- Stars: 15
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# variant-counter
[![Crates.io](https://img.shields.io/crates/v/variant-counter)](https://crates.io/crates/variant_counter)
[![docs.rs](https://img.shields.io/docsrs/variant_counter)](https://docs.rs/variant_counter)The efficient and elegant crate to count variants of Rust's Enum.
## Get started
### `#[derive(VariantCount)]`
```rust
#[derive(VariantCount)]
pub enum Enum {
Variant1,
Variant2,
}
```### Record your variant
```rust
let mut counter = Enum::counter();
counter.record(&Enum::Variant1);
```### Erase the record with `erase_*()` methods
```rust
counter.erase_variant1();
```Those `erase_*()` methods are under `erase` feature flag, and disabled by default.
### Check the record with `check_*()` methods
```rust
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();
```### Ignore a variant
```rust
#[derive(VariantCount)]
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);```
### Aggregate your data```rust
let data = counter.aggregate();
```### Group variants
```rust
#[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();
```
### Statistics```rust
// Sum
counter.sum();// Average
counter.avg();// Variance
counter.variance();// Standard deviation
counter.sd();
```### Weighted
```rust
#[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();
```## Macro expand
You can use [carg-expand](https://crates.io/crates/cargo-expand) to expand the derived `VariantCount` macro.
Here is the expanded code:```rust
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()
}
}
```## Feature flags
- `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`.