Skip to main content

ab_core_primitives/
balance.rs

1//! Balance-related primitives
2
3use ab_io_type::trivial_type::TrivialType;
4use core::cmp::Ordering;
5use core::mem::MaybeUninit;
6use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
7use core::{fmt, ptr};
8
9/// Logically the same as `u128`, but aligned to `8` bytes instead of `16`.
10///
11/// Byte layout is the same as `u128`, just the alignment is different.
12#[derive(Default, Copy, Clone, Eq, PartialEq, Hash, TrivialType)]
13#[repr(C)]
14pub struct Balance(u64, u64);
15
16impl fmt::Debug for Balance {
17    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18        f.debug_tuple("Balance").field(&u128::from(self)).finish()
19    }
20}
21
22impl fmt::Display for Balance {
23    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24        u128::from(self).fmt(f)
25    }
26}
27
28impl Ord for Balance {
29    #[inline(always)]
30    fn cmp(&self, other: &Balance) -> Ordering {
31        u128::from(self).cmp(&u128::from(other))
32    }
33}
34
35impl PartialOrd for Balance {
36    #[inline(always)]
37    fn partial_cmp(&self, other: &Balance) -> Option<Ordering> {
38        Some(self.cmp(other))
39    }
40}
41
42impl Add for Balance {
43    type Output = Balance;
44
45    #[inline(always)]
46    #[track_caller]
47    fn add(self, rhs: Balance) -> Balance {
48        Self::from(u128::from(self).add(u128::from(rhs)))
49    }
50}
51
52impl AddAssign for Balance {
53    #[inline(always)]
54    #[track_caller]
55    fn add_assign(&mut self, rhs: Balance) {
56        *self = *self + rhs;
57    }
58}
59
60impl Sub for Balance {
61    type Output = Balance;
62
63    #[inline(always)]
64    #[track_caller]
65    fn sub(self, rhs: Balance) -> Balance {
66        Self::from(u128::from(self).sub(u128::from(rhs)))
67    }
68}
69
70impl SubAssign for Balance {
71    #[inline(always)]
72    #[track_caller]
73    fn sub_assign(&mut self, rhs: Balance) {
74        *self = *self - rhs;
75    }
76}
77
78impl<Rhs> Mul<Rhs> for Balance
79where
80    u128: Mul<Rhs, Output = u128>,
81{
82    type Output = Balance;
83
84    #[inline(always)]
85    #[track_caller]
86    fn mul(self, rhs: Rhs) -> Balance {
87        Self::from(<u128 as Mul<Rhs>>::mul(u128::from(self), rhs))
88    }
89}
90
91impl<Rhs> MulAssign<Rhs> for Balance
92where
93    u128: Mul<Rhs, Output = u128>,
94{
95    #[inline(always)]
96    #[track_caller]
97    fn mul_assign(&mut self, rhs: Rhs) {
98        *self = *self * rhs;
99    }
100}
101
102impl<Rhs> Div<Rhs> for Balance
103where
104    u128: Div<Rhs, Output = u128>,
105{
106    type Output = Balance;
107
108    #[inline(always)]
109    #[track_caller]
110    fn div(self, rhs: Rhs) -> Balance {
111        Self::from(<u128 as Div<Rhs>>::div(u128::from(self), rhs))
112    }
113}
114
115impl<Rhs> DivAssign<Rhs> for Balance
116where
117    u128: Div<Rhs, Output = u128>,
118{
119    #[inline(always)]
120    #[track_caller]
121    fn div_assign(&mut self, rhs: Rhs) {
122        *self = *self / rhs;
123    }
124}
125
126impl const From<u128> for Balance {
127    #[inline(always)]
128    fn from(value: u128) -> Self {
129        let mut result = MaybeUninit::<Self>::uninit();
130        // SAFETY: correct size, valid pointer, and all bits are valid
131        unsafe {
132            result.as_mut_ptr().cast::<u128>().write_unaligned(value);
133            result.assume_init()
134        }
135    }
136}
137
138impl const From<&Balance> for u128 {
139    #[inline(always)]
140    fn from(value: &Balance) -> Self {
141        // SAFETY: correct size, valid pointer, and all bits are valid
142        unsafe { ptr::from_ref(value).cast::<u128>().read_unaligned() }
143    }
144}
145
146impl const From<Balance> for u128 {
147    #[inline(always)]
148    fn from(value: Balance) -> Self {
149        Self::from(&value)
150    }
151}
152
153impl Balance {
154    /// Minimum balance
155    pub const MIN: Self = Self::from(0);
156    /// Maximum balance
157    pub const MAX: Self = Self::from(u128::MAX);
158}