sqlx_pg_uint/
u64.rs

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