near_primitives_core/
gas.rs

1use crate::errors::IntegerOverflowError;
2use near_gas::NearGas;
3
4/// Wrapper type over [`near_gas::NearGas`], which itself is a wrapper type over u64.
5///
6/// This wrapper exists to maintain JSON RPC compatibility. While [`NearGas`]
7/// serializes to a JSON string for precision, we need to continue serializing
8/// Gas values to JSON numbers for backward compatibility with existing clients.
9///
10/// Note: [`NearGas`] deserialization already handles both JSON numbers and JSON
11/// strings, so we don't need to redefine deserialization behavior here.
12#[derive(
13    borsh::BorshDeserialize,
14    borsh::BorshSerialize,
15    derive_more::Display,
16    derive_more::FromStr,
17    serde::Deserialize,
18    Clone,
19    Copy,
20    PartialEq,
21    Eq,
22    PartialOrd,
23    Ord,
24    Default,
25    Hash,
26)]
27#[repr(transparent)]
28pub struct Gas(NearGas);
29
30impl Gas {
31    /// Maximum value for Gas (u64::MAX)
32    pub const MAX: Gas = Gas::from_gas(u64::MAX);
33    /// Zero value for Gas
34    pub const ZERO: Gas = Gas::from_gas(0);
35
36    /// Creates a new `Gas` from the specified number of whole tera Gas.
37    ///
38    /// # Examples
39    /// ```
40    /// use near_primitives_core::gas::Gas;
41    ///
42    /// let tera_gas = Gas::from_teragas(5);
43    ///
44    /// assert_eq!(tera_gas.as_gas(), 5 * 1_000_000_000_000);
45    /// ```
46    pub const fn from_teragas(inner: u64) -> Self {
47        Self(NearGas::from_tgas(inner))
48    }
49
50    /// Creates a new `Gas` from the specified number of whole giga Gas.
51    ///
52    /// # Examples
53    /// ```
54    /// use near_primitives_core::gas::Gas;
55    ///    
56    /// let giga_gas = Gas::from_gigagas(5);
57    ///
58    /// assert_eq!(giga_gas.as_gas(), 5 * 1_000_000_000);
59    /// ```
60    pub const fn from_gigagas(inner: u64) -> Self {
61        Self(NearGas::from_ggas(inner))
62    }
63
64    /// Creates a new `Gas` from the specified number of whole Gas.
65    ///
66    /// # Examples
67    /// ```
68    /// use near_primitives_core::gas::Gas;
69    ///
70    /// let gas = Gas::from_gas(5 * 1_000_000_000_000);
71    ///
72    /// assert_eq!(gas.as_teragas(), 5);
73    /// ```
74    pub const fn from_gas(inner: u64) -> Self {
75        Self(NearGas::from_gas(inner))
76    }
77
78    /// Returns the total number of whole Gas contained by this `Gas`.
79    ///
80    /// # Examples
81    /// ```
82    /// use near_primitives_core::gas::Gas;
83    ///
84    /// let gas = Gas::from_gas(12345);
85    /// assert_eq!(gas.as_gas(), 12345);
86    /// ```
87    pub const fn as_gas(self) -> u64 {
88        self.0.as_gas()
89    }
90
91    /// Returns the total number of a whole part of giga Gas contained by this `Gas`.
92    ///
93    /// # Examples
94    /// ```
95    /// use near_primitives_core::gas::Gas;
96    ///
97    /// let gas = Gas::from_gigagas(1);
98    /// assert_eq!(gas.as_gigagas(), 1);
99    /// ```
100    pub const fn as_gigagas(self) -> u64 {
101        self.0.as_ggas()
102    }
103
104    /// Returns the total number of a whole part of tera Gas contained by this `Gas`.
105    ///
106    /// # Examples
107    /// ```
108    /// use near_primitives_core::gas::Gas;
109    ///
110    /// let gas = Gas::from_gas(1 * 1_000_000_000_000);
111    /// assert_eq!(gas.as_teragas(), 1);
112    /// ```
113    pub const fn as_teragas(self) -> u64 {
114        self.0.as_tgas()
115    }
116
117    /// Checked integer addition. Computes self + rhs, returning None if overflow occurred.
118    ///
119    /// # Examples
120    /// ```
121    /// use near_primitives_core::gas::Gas;
122    ///
123    /// assert_eq!(Gas::from_gas(u64::MAX -2).checked_add(Gas::from_gas(2)), Some(Gas::MAX));
124    /// assert_eq!(Gas::from_gas(u64::MAX -2).checked_add(Gas::from_gas(3)), None);
125    /// ```
126    pub const fn checked_add(self, rhs: Gas) -> Option<Self> {
127        if let Some(result) = self.0.checked_add(rhs.0) { Some(Self(result)) } else { None }
128    }
129
130    pub fn checked_add_result(self, rhs: Gas) -> Result<Self, IntegerOverflowError> {
131        self.checked_add(rhs).ok_or(IntegerOverflowError)
132    }
133
134    /// Checked integer subtraction. Computes self - rhs, returning None if overflow occurred.
135    ///
136    /// # Examples
137    /// ```
138    /// use near_primitives_core::gas::Gas;
139    ///
140    /// assert_eq!(Gas::from_gas(2).checked_sub(Gas::from_gas(2)), Some(Gas::ZERO));
141    /// assert_eq!(Gas::from_gas(2).checked_sub(Gas::from_gas(3)), None);
142    /// ```
143    pub const fn checked_sub(self, rhs: Gas) -> Option<Self> {
144        if let Some(result) = self.0.checked_sub(rhs.0) { Some(Self(result)) } else { None }
145    }
146
147    /// Checked integer multiplication. Computes self * rhs, returning None if overflow occurred.
148    ///
149    /// # Examples
150    /// ```
151    /// use near_primitives_core::gas::Gas;
152    ///
153    /// use std::u64;
154    /// assert_eq!(Gas::from_gas(2).checked_mul(2), Some(Gas::from_gas(4)));
155    /// assert_eq!(Gas::MAX.checked_mul(2), None)
156    pub const fn checked_mul(self, rhs: u64) -> Option<Self> {
157        if let Some(result) = self.0.checked_mul(rhs) { Some(Self(result)) } else { None }
158    }
159
160    /// Checked integer division. Computes self / rhs, returning None if rhs == 0.
161    ///
162    /// # Examples
163    /// ```
164    /// use near_primitives_core::gas::Gas;
165    ///
166    /// assert_eq!(Gas::from_gas(10).checked_div(2), Some(Gas::from_gas(5)));
167    /// assert_eq!(Gas::from_gas(2).checked_div(0), None);
168    /// ```
169    pub const fn checked_div(self, rhs: u64) -> Option<Self> {
170        if let Some(result) = self.0.checked_div(rhs) { Some(Self(result)) } else { None }
171    }
172
173    /// Saturating integer addition. Computes self + rhs, saturating at the numeric bounds instead of overflowing.
174    ///
175    /// # Examples
176    /// ```
177    /// use near_primitives_core::gas::Gas;
178    /// assert_eq!(Gas::from_gas(5).saturating_add(Gas::from_gas(5)), Gas::from_gas(10));
179    /// assert_eq!(Gas::MAX.saturating_add(Gas::from_gas(1)), Gas::MAX);
180    /// ```
181    pub const fn saturating_add(self, rhs: Gas) -> Gas {
182        Self(self.0.saturating_add(rhs.0))
183    }
184
185    /// Saturating integer subtraction. Computes self - rhs, saturating at the numeric bounds instead of overflowing.
186    ///
187    /// # Examples
188    /// ```
189    /// use near_primitives_core::gas::Gas;
190    /// assert_eq!(Gas::from_gas(5).saturating_sub(Gas::from_gas(2)), Gas::from_gas(3));
191    /// assert_eq!(Gas::from_gas(1).saturating_sub(Gas::from_gas(2)), Gas::ZERO);
192    /// ```
193    pub const fn saturating_sub(self, rhs: Gas) -> Gas {
194        Self(self.0.saturating_sub(rhs.0))
195    }
196
197    /// Saturating integer multiplication. Computes self * rhs, saturating at the numeric bounds instead of overflowing.
198    ///
199    /// # Examples
200    /// ```
201    /// use near_primitives_core::gas::Gas;
202    /// use std::u64;
203    /// assert_eq!(Gas::from_gas(2).saturating_mul(5), Gas::from_gas(10));
204    /// assert_eq!(Gas::MAX.saturating_mul(2), Gas::MAX);
205    /// ```
206    pub const fn saturating_mul(self, rhs: u64) -> Gas {
207        Self(self.0.saturating_mul(rhs))
208    }
209
210    /// Saturating integer division. Computes self / rhs, saturating at the numeric bounds instead of overflowing.
211    ///
212    /// # Examples
213    /// ```
214    /// use near_primitives_core::gas::Gas;
215    /// assert_eq!(Gas::from_gas(10).saturating_div(2), Gas::from_gas(5));
216    /// assert_eq!(Gas::from_gas(10).saturating_div(0), Gas::ZERO)
217    /// ```
218    pub const fn saturating_div(self, rhs: u64) -> Gas {
219        if rhs == 0 {
220            return Gas::ZERO;
221        }
222        Self(self.0.saturating_div(rhs))
223    }
224}
225
226impl serde::Serialize for Gas {
227    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
228    where
229        S: serde::Serializer,
230    {
231        serializer.serialize_u64(self.as_gas())
232    }
233}
234
235impl core::fmt::Debug for Gas {
236    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
237        write!(f, "{}", self.as_gas())
238    }
239}
240
241#[cfg(feature = "schemars")]
242impl schemars::JsonSchema for Gas {
243    fn schema_name() -> std::borrow::Cow<'static, str> {
244        "NearGas".to_string().into()
245    }
246
247    fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
248        schemars::json_schema!({
249            "format": "uint64",
250            "minimum": 0,
251            "type": "integer"
252        })
253    }
254}