gear_common/storage/complicated/counter.rs
1// Copyright (C) Gear Technologies Inc.
2// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
3
4//! Module for counter implementation.
5//!
6//! Counter provides API for step-by-step changing of the value.
7//! Could be used to count amount of some parameter.
8
9use crate::storage::ValueStorage;
10use core::marker::PhantomData;
11
12/// Represents logic of managing step-by-step changeable value.
13pub trait Counter {
14 /// Counter stored type.
15 type Value;
16
17 /// Decreases stored value.
18 ///
19 /// Should be safe from overflow.
20 fn decrease();
21
22 /// Returns stored value, if present, or default/starting value.
23 fn get() -> Self::Value;
24
25 /// Increases stored value.
26 ///
27 /// Should be safe from overflow.
28 fn increase();
29
30 /// Resets stored value by setting default/starting value.
31 fn reset();
32}
33
34/// `Counter` implementation based on `ValueStorage`.
35///
36/// Generic parameter `T` presents inner storing type.
37pub struct CounterImpl<T, VS: ValueStorage<Value = T>>(PhantomData<VS>);
38
39/// Crate local macro for repeating `Counter` implementation
40/// over `ValueStorage` with Rust's numeric types.
41macro_rules! impl_counter {
42 ($($t: ty), +) => { $(
43 impl<VS: ValueStorage<Value = $t>> Counter for CounterImpl<$t, VS> {
44 type Value = VS::Value;
45
46 fn decrease() {
47 VS::mutate(|opt_val| {
48 if let Some(val) = opt_val {
49 *val = val.saturating_sub(1);
50 }
51 });
52 }
53
54 fn get() -> Self::Value {
55 VS::get().unwrap_or(0)
56 }
57
58 fn increase() {
59 VS::mutate(|opt_val| {
60 if let Some(val) = opt_val {
61 *val = val.saturating_add(1);
62 } else {
63 *opt_val = Some(1)
64 }
65 });
66 }
67
68 fn reset() {
69 VS::put(0);
70 }
71 }
72 ) + };
73}
74
75// Implementation for unsigned integers.
76impl_counter!(u8, u16, u32, u64, u128);
77
78// Implementation for signed integers.
79impl_counter!(i8, i16, i32, i64, i128);