1use super::*;
2use sqlx_pg_uint_macros::UIntWrapper;
3
4use crate::UIntType;
5
6impl private::Sealed for PgU128 {}
7
8impl UIntType for PgU128 {
9 type Uint = u128;
10}
11
12#[derive(Debug, PartialEq, Eq, Clone, Hash, PartialOrd, Ord, UIntWrapper, sqlx::FromRow)]
13pub struct PgU128 {
15 inner: BigDecimal,
16}
17
18impl From<PgU128> for u128 {
19 fn from(value: PgU128) -> Self {
20 value.inner.to_string().parse().unwrap()
21 }
22}
23
24impl From<u128> for PgU128 {
25 fn from(value: u128) -> Self {
26 Self {
27 inner: BigDecimal::from(value),
28 }
29 }
30}
31
32#[cfg(test)]
33mod pg_u128_tests {
34 use bigdecimal::num_bigint::BigInt;
35
36 use super::*;
37
38 #[test]
39 fn test_to_u128() {
40 let pg_u128 = PgU128::from(12678671u128);
41 assert_eq!(pg_u128.to_uint(), 12678671u128);
42 let pg_u128 = PgU128::from(0);
43 assert_eq!(pg_u128.to_uint(), 0u128);
44 let pg_u128 = PgU128::from(u128::MAX);
45 assert_eq!(pg_u128.to_uint(), u128::MAX);
46 }
47
48 #[test]
49 fn test_add() {
50 let pg_u128 = PgU128::from(12678671u128);
51 let pg_u1282 = PgU128::from(12678671u128);
52 assert_eq!((pg_u128 + pg_u1282).to_uint(), 25357342u128);
53
54 let pg_u128 = PgU128::from(0u128);
55 let pg_u1282 = PgU128::from(0u128);
56 assert_eq!((pg_u128 + pg_u1282).to_uint(), 0u128);
57 }
58
59 #[test]
60 #[should_panic]
61 fn test_add_overflow() {
62 let pg_u128 = PgU128::from(u128::MAX);
63 let pg_u1282 = PgU128::from(1u128);
64 let _ = pg_u128 + pg_u1282;
65 }
66
67 #[test]
68 #[should_panic]
69 fn test_add_underflow() {
70 let pg_u128 = PgU128::from(0u128);
71 let pg_u1282 = PgU128::from(1u128);
72 let _ = pg_u128 - pg_u1282;
73 }
74
75 #[test]
76 fn try_from_bigdecimal() {
77 let pg_u128 = PgU128::try_from(BigDecimal::from(12678671u128)).unwrap();
78 assert_eq!(pg_u128.to_uint(), 12678671u128);
79
80 let pg_u128 = PgU128::try_from(BigDecimal::from(0)).unwrap();
81 assert_eq!(pg_u128.to_uint(), 0u128);
82
83 let pg_u128 = PgU128::try_from(BigDecimal::from(u128::MAX)).unwrap();
84 assert_eq!(pg_u128.to_uint(), u128::MAX);
85
86 let pg_u128 = PgU128::try_from(BigDecimal::from(-1));
87 assert!(pg_u128.is_err());
88 let err = pg_u128.unwrap_err();
89 assert_eq!(err, Error::InvalidValue(BigDecimal::from(-1)));
90
91 let fractional = BigDecimal::from(3) / BigDecimal::from(2);
92 let pg_u128 = PgU128::try_from(fractional.clone());
93 assert_eq!(pg_u128.unwrap_err(), Error::Fractional(fractional));
94
95 let big_decimal = BigDecimal::from(BigInt::from(2).pow(128));
96 let pg_u128 = PgU128::try_from(big_decimal.clone());
97 assert_eq!(pg_u128.unwrap_err(), Error::InvalidValue(big_decimal));
98 }
99
100 #[test]
101 fn test_option_conversion() {
102 let somepguint = Some(PgU128::from(123u128));
103 let someuint = somepguint.to_option_uint();
104 assert_eq!(someuint, Some(123u128));
105
106 let pguint = PgU128::from(123);
107 let someuint = pguint.to_option_uint();
108 assert_eq!(someuint, Some(123u128));
109
110 let pguint: Option<PgU128> = None;
111 let someuint = pguint.to_option_uint();
112 assert_eq!(someuint, None::<u128>);
113 }
114}