1use alloc::vec::Vec;
4use core::{
5 fmt,
6 iter::Sum,
7 ops::{Add, Div, Mul, Sub},
8};
9
10#[cfg(feature = "datasize")]
11use datasize::DataSize;
12use num::Zero;
13use serde::{Deserialize, Serialize};
14
15use crate::{
16 bytesrepr::{self, FromBytes, ToBytes},
17 Gas, U512,
18};
19
20#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
22#[cfg_attr(feature = "datasize", derive(DataSize))]
23pub struct Motes(U512);
24
25impl Motes {
26 pub fn new(value: U512) -> Motes {
28 Motes(value)
29 }
30
31 pub fn checked_add(&self, rhs: Self) -> Option<Self> {
33 self.0.checked_add(rhs.value()).map(Self::new)
34 }
35
36 pub fn checked_sub(&self, rhs: Self) -> Option<Self> {
38 self.0.checked_sub(rhs.value()).map(Self::new)
39 }
40
41 pub fn value(&self) -> U512 {
43 self.0
44 }
45
46 pub fn from_gas(gas: Gas, conv_rate: u64) -> Option<Self> {
50 gas.value()
51 .checked_mul(U512::from(conv_rate))
52 .map(Self::new)
53 }
54}
55
56impl fmt::Display for Motes {
57 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
58 write!(f, "{:?}", self.0)
59 }
60}
61
62impl Add for Motes {
63 type Output = Motes;
64
65 fn add(self, rhs: Self) -> Self::Output {
66 let val = self.value() + rhs.value();
67 Motes::new(val)
68 }
69}
70
71impl Sub for Motes {
72 type Output = Motes;
73
74 fn sub(self, rhs: Self) -> Self::Output {
75 let val = self.value() - rhs.value();
76 Motes::new(val)
77 }
78}
79
80impl Div for Motes {
81 type Output = Motes;
82
83 fn div(self, rhs: Self) -> Self::Output {
84 let val = self.value() / rhs.value();
85 Motes::new(val)
86 }
87}
88
89impl Mul for Motes {
90 type Output = Motes;
91
92 fn mul(self, rhs: Self) -> Self::Output {
93 let val = self.value() * rhs.value();
94 Motes::new(val)
95 }
96}
97
98impl Zero for Motes {
99 fn zero() -> Self {
100 Motes::new(U512::zero())
101 }
102
103 fn is_zero(&self) -> bool {
104 self.0.is_zero()
105 }
106}
107
108impl Sum for Motes {
109 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
110 iter.fold(Motes::zero(), Add::add)
111 }
112}
113
114impl ToBytes for Motes {
115 fn to_bytes(&self) -> Result<Vec<u8>, bytesrepr::Error> {
116 self.0.to_bytes()
117 }
118
119 fn serialized_length(&self) -> usize {
120 self.0.serialized_length()
121 }
122}
123
124impl FromBytes for Motes {
125 fn from_bytes(bytes: &[u8]) -> Result<(Self, &[u8]), bytesrepr::Error> {
126 let (value, remainder) = FromBytes::from_bytes(bytes)?;
127 Ok((Motes::new(value), remainder))
128 }
129}
130
131#[cfg(test)]
132mod tests {
133 use crate::U512;
134
135 use crate::{Gas, Motes};
136
137 #[test]
138 fn should_be_able_to_get_instance_of_motes() {
139 let initial_value = 1;
140 let motes = Motes::new(U512::from(initial_value));
141 assert_eq!(
142 initial_value,
143 motes.value().as_u64(),
144 "should have equal value"
145 )
146 }
147
148 #[test]
149 fn should_be_able_to_compare_two_instances_of_motes() {
150 let left_motes = Motes::new(U512::from(1));
151 let right_motes = Motes::new(U512::from(1));
152 assert_eq!(left_motes, right_motes, "should be equal");
153 let right_motes = Motes::new(U512::from(2));
154 assert_ne!(left_motes, right_motes, "should not be equal")
155 }
156
157 #[test]
158 fn should_be_able_to_add_two_instances_of_motes() {
159 let left_motes = Motes::new(U512::from(1));
160 let right_motes = Motes::new(U512::from(1));
161 let expected_motes = Motes::new(U512::from(2));
162 assert_eq!(
163 (left_motes + right_motes),
164 expected_motes,
165 "should be equal"
166 )
167 }
168
169 #[test]
170 fn should_be_able_to_subtract_two_instances_of_motes() {
171 let left_motes = Motes::new(U512::from(1));
172 let right_motes = Motes::new(U512::from(1));
173 let expected_motes = Motes::new(U512::from(0));
174 assert_eq!(
175 (left_motes - right_motes),
176 expected_motes,
177 "should be equal"
178 )
179 }
180
181 #[test]
182 fn should_be_able_to_multiply_two_instances_of_motes() {
183 let left_motes = Motes::new(U512::from(100));
184 let right_motes = Motes::new(U512::from(10));
185 let expected_motes = Motes::new(U512::from(1000));
186 assert_eq!(
187 (left_motes * right_motes),
188 expected_motes,
189 "should be equal"
190 )
191 }
192
193 #[test]
194 fn should_be_able_to_divide_two_instances_of_motes() {
195 let left_motes = Motes::new(U512::from(1000));
196 let right_motes = Motes::new(U512::from(100));
197 let expected_motes = Motes::new(U512::from(10));
198 assert_eq!(
199 (left_motes / right_motes),
200 expected_motes,
201 "should be equal"
202 )
203 }
204
205 #[test]
206 fn should_be_able_to_convert_from_motes() {
207 let gas = Gas::new(U512::from(100));
208 let motes = Motes::from_gas(gas, 10).expect("should have value");
209 let expected_motes = Motes::new(U512::from(1000));
210 assert_eq!(motes, expected_motes, "should be equal")
211 }
212
213 #[test]
214 fn should_be_able_to_default() {
215 let motes = Motes::default();
216 let expected_motes = Motes::new(U512::from(0));
217 assert_eq!(motes, expected_motes, "should be equal")
218 }
219
220 #[test]
221 fn should_be_able_to_compare_relative_value() {
222 let left_motes = Motes::new(U512::from(100));
223 let right_motes = Motes::new(U512::from(10));
224 assert!(left_motes > right_motes, "should be gt");
225 let right_motes = Motes::new(U512::from(100));
226 assert!(left_motes >= right_motes, "should be gte");
227 assert!(left_motes <= right_motes, "should be lte");
228 let left_motes = Motes::new(U512::from(10));
229 assert!(left_motes < right_motes, "should be lt");
230 }
231
232 #[test]
233 fn should_default() {
234 let left_motes = Motes::new(U512::from(0));
235 let right_motes = Motes::default();
236 assert_eq!(left_motes, right_motes, "should be equal");
237 let u512 = U512::zero();
238 assert_eq!(left_motes.value(), u512, "should be equal");
239 }
240
241 #[test]
242 fn should_support_checked_mul_from_gas() {
243 let gas = Gas::new(U512::MAX);
244 let conv_rate = 10;
245 let maybe = Motes::from_gas(gas, conv_rate);
246 assert!(maybe.is_none(), "should be none due to overflow");
247 }
248}