1use schemars::JsonSchema;
2use serde::{de, ser, Deserialize, Deserializer, Serialize};
3use std::convert::{TryFrom, TryInto};
4use std::fmt;
5use std::iter::Sum;
6use std::ops::{self, Shr};
7use std::str::FromStr;
8
9use crate::errors::{
10 ConversionOverflowError, DivideByZeroError, OverflowError, OverflowOperation, StdError,
11};
12use crate::{Uint128, Uint256, Uint64};
13
14#[allow(clippy::all)]
17mod uints {
18 uint::construct_uint! {
19 pub struct U512(8);
20 }
21}
22
23use uints::U512;
26
27#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, JsonSchema)]
52pub struct Uint512(#[schemars(with = "String")] U512);
53
54impl Uint512 {
55 pub const MAX: Uint512 = Uint512(U512::MAX);
56
57 pub fn new(value: [u8; 64]) -> Self {
60 Self::from_be_bytes(value)
61 }
62
63 pub const fn zero() -> Self {
65 Uint512(U512::zero())
66 }
67
68 pub fn from_be_bytes(value: [u8; 64]) -> Self {
69 Uint512(U512::from_big_endian(&value))
70 }
71
72 pub fn from_le_bytes(value: [u8; 64]) -> Self {
73 Uint512(U512::from_little_endian(&value))
74 }
75
76 pub fn to_be_bytes(self) -> [u8; 64] {
78 let mut result = [0u8; 64];
79 self.0.to_big_endian(&mut result);
80 result
81 }
82
83 pub fn to_le_bytes(self) -> [u8; 64] {
85 let mut result = [0u8; 64];
86 self.0.to_little_endian(&mut result);
87 result
88 }
89
90 pub fn is_zero(&self) -> bool {
91 self.0.is_zero()
92 }
93
94 pub fn checked_add(self, other: Self) -> Result<Self, OverflowError> {
95 self.0
96 .checked_add(other.0)
97 .map(Self)
98 .ok_or_else(|| OverflowError::new(OverflowOperation::Add, self, other))
99 }
100
101 pub fn checked_sub(self, other: Self) -> Result<Self, OverflowError> {
102 self.0
103 .checked_sub(other.0)
104 .map(Self)
105 .ok_or_else(|| OverflowError::new(OverflowOperation::Sub, self, other))
106 }
107
108 pub fn checked_mul(self, other: Self) -> Result<Self, OverflowError> {
109 self.0
110 .checked_mul(other.0)
111 .map(Self)
112 .ok_or_else(|| OverflowError::new(OverflowOperation::Mul, self, other))
113 }
114
115 pub fn checked_div(self, other: Self) -> Result<Self, DivideByZeroError> {
116 self.0
117 .checked_div(other.0)
118 .map(Self)
119 .ok_or_else(|| DivideByZeroError::new(self))
120 }
121
122 pub fn checked_rem(self, other: Self) -> Result<Self, DivideByZeroError> {
123 self.0
124 .checked_rem(other.0)
125 .map(Self)
126 .ok_or_else(|| DivideByZeroError::new(self))
127 }
128
129 pub fn checked_shr(self, other: u32) -> Result<Self, OverflowError> {
130 if other >= 512 {
131 return Err(OverflowError::new(OverflowOperation::Shr, self, other));
132 }
133
134 Ok(Self(self.0.shr(other)))
135 }
136
137 pub fn saturating_add(self, other: Self) -> Self {
138 Self(self.0.saturating_add(other.0))
139 }
140
141 pub fn saturating_sub(self, other: Self) -> Self {
142 Self(self.0.saturating_sub(other.0))
143 }
144
145 pub fn saturating_mul(self, other: Self) -> Self {
146 Self(self.0.saturating_mul(other.0))
147 }
148}
149
150impl From<Uint256> for Uint512 {
151 fn from(val: Uint256) -> Self {
152 let bytes = [[0u8; 32], val.to_be_bytes()].concat();
153
154 Self::from_be_bytes(bytes.try_into().unwrap())
155 }
156}
157
158impl From<Uint128> for Uint512 {
159 fn from(val: Uint128) -> Self {
160 val.u128().into()
161 }
162}
163
164impl From<Uint64> for Uint512 {
165 fn from(val: Uint64) -> Self {
166 val.u64().into()
167 }
168}
169
170impl From<u128> for Uint512 {
171 fn from(val: u128) -> Self {
172 Uint512(val.into())
173 }
174}
175
176impl From<u64> for Uint512 {
177 fn from(val: u64) -> Self {
178 Uint512(val.into())
179 }
180}
181
182impl From<u32> for Uint512 {
183 fn from(val: u32) -> Self {
184 Uint512(val.into())
185 }
186}
187
188impl From<u16> for Uint512 {
189 fn from(val: u16) -> Self {
190 Uint512(val.into())
191 }
192}
193
194impl From<u8> for Uint512 {
195 fn from(val: u8) -> Self {
196 Uint512(val.into())
197 }
198}
199
200impl TryFrom<Uint512> for Uint256 {
201 type Error = ConversionOverflowError;
202
203 fn try_from(value: Uint512) -> Result<Self, Self::Error> {
204 let bytes = value.to_be_bytes();
205 let (first_bytes, last_bytes) = bytes.split_at(32);
206
207 if first_bytes != [0u8; 32] {
208 return Err(ConversionOverflowError::new(
209 "Uint512",
210 "Uint256",
211 value.to_string(),
212 ));
213 }
214
215 Ok(Self::from_be_bytes(last_bytes.try_into().unwrap()))
216 }
217}
218
219impl TryFrom<Uint512> for Uint128 {
220 type Error = ConversionOverflowError;
221
222 fn try_from(value: Uint512) -> Result<Self, Self::Error> {
223 Ok(Uint128::new(value.0.try_into().map_err(|_| {
224 ConversionOverflowError::new("Uint512", "Uint128", value.to_string())
225 })?))
226 }
227}
228
229impl TryFrom<&str> for Uint512 {
230 type Error = StdError;
231
232 fn try_from(val: &str) -> Result<Self, Self::Error> {
233 Self::from_str(val)
234 }
235}
236
237impl FromStr for Uint512 {
238 type Err = StdError;
239
240 fn from_str(s: &str) -> Result<Self, Self::Err> {
241 match U512::from_dec_str(s) {
242 Ok(u) => Ok(Self(u)),
243 Err(e) => Err(StdError::generic_err(format!("Parsing u512: {}", e))),
244 }
245 }
246}
247
248impl From<Uint512> for String {
249 fn from(original: Uint512) -> Self {
250 original.to_string()
251 }
252}
253
254impl fmt::Display for Uint512 {
255 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
256 let unpadded = self.0.to_string();
259
260 f.pad_integral(true, "", &unpadded)
261 }
262}
263
264impl ops::Add<Uint512> for Uint512 {
265 type Output = Self;
266
267 fn add(self, rhs: Self) -> Self {
268 Uint512(self.0.checked_add(rhs.0).unwrap())
269 }
270}
271
272impl<'a> ops::Add<&'a Uint512> for Uint512 {
273 type Output = Self;
274
275 fn add(self, rhs: &'a Uint512) -> Self {
276 Uint512(self.0.checked_add(rhs.0).unwrap())
277 }
278}
279
280impl ops::Sub<Uint512> for Uint512 {
281 type Output = Self;
282
283 fn sub(self, rhs: Self) -> Self {
284 Uint512(self.0.checked_sub(rhs.0).unwrap())
285 }
286}
287
288impl<'a> ops::Sub<&'a Uint512> for Uint512 {
289 type Output = Self;
290
291 fn sub(self, rhs: &'a Uint512) -> Self {
292 Uint512(self.0.checked_sub(rhs.0).unwrap())
293 }
294}
295
296impl ops::Div<Uint512> for Uint512 {
297 type Output = Self;
298
299 fn div(self, rhs: Self) -> Self::Output {
300 Self(self.0.checked_div(rhs.0).unwrap())
301 }
302}
303
304impl<'a> ops::Div<&'a Uint512> for Uint512 {
305 type Output = Self;
306
307 fn div(self, rhs: &'a Uint512) -> Self::Output {
308 Self(self.0.checked_div(rhs.0).unwrap())
309 }
310}
311
312impl ops::Mul<Uint512> for Uint512 {
313 type Output = Self;
314
315 fn mul(self, rhs: Self) -> Self::Output {
316 Self(self.0.checked_mul(rhs.0).unwrap())
317 }
318}
319
320impl<'a> ops::Mul<&'a Uint512> for Uint512 {
321 type Output = Self;
322
323 fn mul(self, rhs: &'a Uint512) -> Self::Output {
324 Self(self.0.checked_mul(rhs.0).unwrap())
325 }
326}
327
328impl ops::Shr<u32> for Uint512 {
329 type Output = Self;
330
331 fn shr(self, rhs: u32) -> Self::Output {
332 self.checked_shr(rhs).unwrap_or_else(|_| {
333 panic!(
334 "right shift error: {} is larger or equal than the number of bits in Uint512",
335 rhs,
336 )
337 })
338 }
339}
340
341impl<'a> ops::Shr<&'a u32> for Uint512 {
342 type Output = Self;
343
344 fn shr(self, rhs: &'a u32) -> Self::Output {
345 Shr::<u32>::shr(self, *rhs)
346 }
347}
348
349impl ops::AddAssign<Uint512> for Uint512 {
350 fn add_assign(&mut self, rhs: Uint512) {
351 self.0 = self.0.checked_add(rhs.0).unwrap();
352 }
353}
354
355impl<'a> ops::AddAssign<&'a Uint512> for Uint512 {
356 fn add_assign(&mut self, rhs: &'a Uint512) {
357 self.0 = self.0.checked_add(rhs.0).unwrap();
358 }
359}
360
361impl ops::SubAssign<Uint512> for Uint512 {
362 fn sub_assign(&mut self, rhs: Uint512) {
363 self.0 = self.0.checked_sub(rhs.0).unwrap();
364 }
365}
366
367impl<'a> ops::SubAssign<&'a Uint512> for Uint512 {
368 fn sub_assign(&mut self, rhs: &'a Uint512) {
369 self.0 = self.0.checked_sub(rhs.0).unwrap();
370 }
371}
372
373impl ops::DivAssign<Uint512> for Uint512 {
374 fn div_assign(&mut self, rhs: Self) {
375 self.0 = self.0.checked_div(rhs.0).unwrap();
376 }
377}
378
379impl<'a> ops::DivAssign<&'a Uint512> for Uint512 {
380 fn div_assign(&mut self, rhs: &'a Uint512) {
381 self.0 = self.0.checked_div(rhs.0).unwrap();
382 }
383}
384
385impl ops::MulAssign<Uint512> for Uint512 {
386 fn mul_assign(&mut self, rhs: Self) {
387 self.0 = self.0.checked_mul(rhs.0).unwrap();
388 }
389}
390
391impl<'a> ops::MulAssign<&'a Uint512> for Uint512 {
392 fn mul_assign(&mut self, rhs: &'a Uint512) {
393 self.0 = self.0.checked_mul(rhs.0).unwrap();
394 }
395}
396
397impl ops::ShrAssign<u32> for Uint512 {
398 fn shr_assign(&mut self, rhs: u32) {
399 *self = Shr::<u32>::shr(*self, rhs);
400 }
401}
402
403impl<'a> ops::ShrAssign<&'a u32> for Uint512 {
404 fn shr_assign(&mut self, rhs: &'a u32) {
405 *self = Shr::<u32>::shr(*self, *rhs);
406 }
407}
408
409impl Serialize for Uint512 {
410 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
412 where
413 S: ser::Serializer,
414 {
415 serializer.serialize_str(&self.to_string())
416 }
417}
418
419impl<'de> Deserialize<'de> for Uint512 {
420 fn deserialize<D>(deserializer: D) -> Result<Uint512, D::Error>
422 where
423 D: Deserializer<'de>,
424 {
425 deserializer.deserialize_str(Uint512Visitor)
426 }
427}
428
429struct Uint512Visitor;
430
431impl<'de> de::Visitor<'de> for Uint512Visitor {
432 type Value = Uint512;
433
434 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
435 formatter.write_str("string-encoded integer")
436 }
437
438 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
439 where
440 E: de::Error,
441 {
442 Uint512::try_from(v).map_err(|e| E::custom(format!("invalid Uint512 '{}' - {}", v, e)))
443 }
444}
445
446impl Sum<Uint512> for Uint512 {
447 fn sum<I: Iterator<Item = Uint512>>(iter: I) -> Self {
448 iter.fold(Uint512::zero(), ops::Add::add)
449 }
450}
451
452impl<'a> Sum<&'a Uint512> for Uint512 {
453 fn sum<I: Iterator<Item = &'a Uint512>>(iter: I) -> Self {
454 iter.fold(Uint512::zero(), ops::Add::add)
455 }
456}
457
458#[cfg(test)]
459mod tests {
460 use super::*;
461 use crate::{from_slice, to_vec};
462
463 #[test]
464 fn uint512_construct() {
465 let num = Uint512::new([1; 64]);
466 let a: [u8; 64] = num.to_be_bytes();
467 assert_eq!(a, [1; 64]);
468
469 let be_bytes = [
470 0u8, 222u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
471 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
472 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
473 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, 3u8,
474 ];
475 let num = Uint512::new(be_bytes);
476 let resulting_bytes: [u8; 64] = num.to_be_bytes();
477 assert_eq!(be_bytes, resulting_bytes);
478 }
479
480 #[test]
481 fn uint512_endianness() {
482 let be_bytes = [
483 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
484 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
485 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
486 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 1u8, 2u8, 3u8,
487 ];
488 let le_bytes = [
489 3u8, 2u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
490 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
491 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
492 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
493 ];
494
495 let num1 = Uint512::new(be_bytes);
497 let num2 = Uint512::from_be_bytes(be_bytes);
498 let num3 = Uint512::from_le_bytes(le_bytes);
499 assert_eq!(num1, Uint512::from(65536u32 + 512 + 3));
500 assert_eq!(num1, num2);
501 assert_eq!(num1, num3);
502 }
503
504 #[test]
505 fn uint512_convert_from() {
506 let a = Uint512::from(5u128);
507 assert_eq!(a.0, U512::from(5));
508
509 let a = Uint512::from(5u64);
510 assert_eq!(a.0, U512::from(5));
511
512 let a = Uint512::from(5u32);
513 assert_eq!(a.0, U512::from(5));
514
515 let a = Uint512::from(5u16);
516 assert_eq!(a.0, U512::from(5));
517
518 let a = Uint512::from(5u8);
519 assert_eq!(a.0, U512::from(5));
520
521 let result = Uint512::try_from("34567");
522 assert_eq!(result.unwrap().0, U512::from_dec_str("34567").unwrap());
523
524 let result = Uint512::try_from("1.23");
525 assert!(result.is_err());
526 }
527
528 #[test]
529 fn uint512_convert_to_uint128() {
530 let source = Uint512::from(42u128);
531 let target = Uint128::try_from(source);
532 assert_eq!(target, Ok(Uint128::new(42u128)));
533
534 let source = Uint512::MAX;
535 let target = Uint128::try_from(source);
536 assert_eq!(
537 target,
538 Err(ConversionOverflowError::new(
539 "Uint512",
540 "Uint128",
541 Uint512::MAX.to_string()
542 ))
543 );
544 }
545
546 #[test]
547 fn uint512_implements_display() {
548 let a = Uint512::from(12345u32);
549 assert_eq!(format!("Embedded: {}", a), "Embedded: 12345");
550 assert_eq!(a.to_string(), "12345");
551
552 let a = Uint512::zero();
553 assert_eq!(format!("Embedded: {}", a), "Embedded: 0");
554 assert_eq!(a.to_string(), "0");
555 }
556
557 #[test]
558 fn uint512_display_padding_works() {
559 let a = Uint512::from(123u64);
560 assert_eq!(format!("Embedded: {:05}", a), "Embedded: 00123");
561 }
562
563 #[test]
564 fn uint512_is_zero_works() {
565 assert!(Uint512::zero().is_zero());
566 assert!(Uint512(U512::from(0)).is_zero());
567
568 assert!(!Uint512::from(1u32).is_zero());
569 assert!(!Uint512::from(123u32).is_zero());
570 }
571
572 #[test]
573 fn uint512_json() {
574 let orig = Uint512::from(1234567890987654321u128);
575 let serialized = to_vec(&orig).unwrap();
576 assert_eq!(serialized.as_slice(), b"\"1234567890987654321\"");
577 let parsed: Uint512 = from_slice(&serialized).unwrap();
578 assert_eq!(parsed, orig);
579 }
580
581 #[test]
582 fn uint512_compare() {
583 let a = Uint512::from(12345u32);
584 let b = Uint512::from(23456u32);
585
586 assert!(a < b);
587 assert!(b > a);
588 assert_eq!(a, Uint512::from(12345u32));
589 }
590
591 #[test]
592 #[allow(clippy::op_ref)]
593 fn uint512_math() {
594 let a = Uint512::from(12345u32);
595 let b = Uint512::from(23456u32);
596
597 assert_eq!(a + b, Uint512::from(35801u32));
599 assert_eq!(a + &b, Uint512::from(35801u32));
600
601 assert_eq!(b - a, Uint512::from(11111u32));
603 assert_eq!(b - &a, Uint512::from(11111u32));
604
605 let mut c = Uint512::from(300000u32);
607 c += b;
608 assert_eq!(c, Uint512::from(323456u32));
609 let mut d = Uint512::from(300000u32);
610 d += &b;
611 assert_eq!(d, Uint512::from(323456u32));
612
613 let mut c = Uint512::from(300000u32);
615 c -= b;
616 assert_eq!(c, Uint512::from(276544u32));
617 let mut d = Uint512::from(300000u32);
618 d -= &b;
619 assert_eq!(d, Uint512::from(276544u32));
620
621 let underflow_result = a.checked_sub(b);
623 let OverflowError {
624 operand1, operand2, ..
625 } = underflow_result.unwrap_err();
626 assert_eq!((operand1, operand2), (a.to_string(), b.to_string()));
627 }
628
629 #[test]
630 #[should_panic]
631 fn uint512_add_overflow_panics() {
632 let max = Uint512::new([255u8; 64]);
633 let _ = max + Uint512::from(12u32);
634 }
635
636 #[test]
637 #[should_panic]
638 fn uint512_sub_overflow_panics() {
639 let _ = Uint512::from(1u32) - Uint512::from(2u32);
640 }
641
642 #[test]
643 fn uint512_shr_works() {
644 let original = Uint512::new([
645 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
646 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
647 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
648 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 2u8, 0u8, 4u8, 2u8,
649 ]);
650
651 let shifted = Uint512::new([
652 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
653 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
654 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
655 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 128u8, 1u8, 0u8,
656 ]);
657
658 assert_eq!(original >> 2u32, shifted);
659 }
660
661 #[test]
662 #[should_panic]
663 fn uint512_shr_overflow_panics() {
664 let _ = Uint512::from(1u32) >> 512u32;
665 }
666
667 #[test]
668 fn sum_works() {
669 let nums = vec![
670 Uint512::from(17u32),
671 Uint512::from(123u32),
672 Uint512::from(540u32),
673 Uint512::from(82u32),
674 ];
675 let expected = Uint512::from(762u32);
676
677 let sum_as_ref = nums.iter().sum();
678 assert_eq!(expected, sum_as_ref);
679
680 let sum_as_owned = nums.into_iter().sum();
681 assert_eq!(expected, sum_as_owned);
682 }
683
684 #[test]
685 fn uint512_methods() {
686 assert!(matches!(
688 Uint512::MAX.checked_add(Uint512::from(1u32)),
689 Err(OverflowError { .. })
690 ));
691 assert!(matches!(
692 Uint512::from(0u32).checked_sub(Uint512::from(1u32)),
693 Err(OverflowError { .. })
694 ));
695 assert!(matches!(
696 Uint512::MAX.checked_mul(Uint512::from(2u32)),
697 Err(OverflowError { .. })
698 ));
699 assert!(matches!(
700 Uint512::MAX.checked_div(Uint512::from(0u32)),
701 Err(DivideByZeroError { .. })
702 ));
703 assert!(matches!(
704 Uint512::MAX.checked_rem(Uint512::from(0u32)),
705 Err(DivideByZeroError { .. })
706 ));
707
708 assert_eq!(
710 Uint512::MAX.saturating_add(Uint512::from(1u32)),
711 Uint512::MAX
712 );
713 assert_eq!(
714 Uint512::from(0u32).saturating_sub(Uint512::from(1u32)),
715 Uint512::from(0u32)
716 );
717 assert_eq!(
718 Uint512::MAX.saturating_mul(Uint512::from(2u32)),
719 Uint512::MAX
720 );
721 }
722}