Skip to main content

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);