Skip to main content

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