gear_common/storage/complicated/limiter.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 limiter implementation.
5//!
6//! Limiter provides API for continually descending value.
7//! Could be used to prevent (limit) some value from overflow.
8
9use crate::storage::ValueStorage;
10use core::marker::PhantomData;
11
12/// Represents logic of limiting value decreasing.
13pub trait Limiter {
14 /// Limiter stored type.
15 type Value;
16
17 /// Decreases stored value.
18 ///
19 /// Should be safe from overflow.
20 fn decrease(value: Self::Value);
21
22 /// Returns stored value, if present,
23 /// or default/nullable value.
24 fn get() -> Self::Value;
25
26 /// Puts given value into stored, to start from
27 /// new one for future decreasing.
28 fn put(value: Self::Value);
29}
30
31/// `Limiter` implementation based on `ValueStorage`.
32///
33/// Generic parameter `T` represents inner storing type.
34pub struct LimiterImpl<T, VS: ValueStorage<Value = T>>(PhantomData<VS>);
35
36/// Crate local macro for repeating `Limiter` implementation
37/// over `ValueStorage` with Rust's numeric types.
38macro_rules! impl_limiter {
39 ($($t: ty), +) => { $(
40 impl<VS: ValueStorage<Value = $t>> Limiter for LimiterImpl<$t, VS> {
41 type Value = VS::Value;
42
43 fn decrease(value: Self::Value) {
44 VS::mutate(|opt_val| {
45 if let Some(val) = opt_val {
46 *val = val.saturating_sub(value);
47 }
48 });
49 }
50
51 fn get() -> Self::Value {
52 VS::get().unwrap_or(0)
53 }
54
55 fn put(value: Self::Value) {
56 VS::put(value);
57 }
58 }
59 ) + };
60}
61
62// Implementation for unsigned integers.
63impl_limiter!(u8, u16, u32, u64, u128);
64
65// Implementation for signed integers.
66impl_limiter!(i8, i16, i32, i64, i128);