Skip to main content

sui_graphql/
scalars.rs

1//! GraphQL scalar types for Sui.
2
3use std::borrow::Cow;
4
5use serde::Deserialize;
6
7/// `SuiAddress` scalar in Sui GraphQL schema. 32-byte hex-encoded address with `0x` prefix.
8pub use sui_sdk_types::Address;
9
10/// Useful for digest fields (Base58 string). Not a scalar in Sui GraphQL schema.
11pub use sui_sdk_types::Digest;
12
13/// `BigInt` scalar in Sui GraphQL schema.
14///
15/// Represented as a string because JSON numbers cannot reliably represent large integers.
16/// The underlying type defaults to `u64` and can be any signed or unsigned primitive integer
17/// type, or [`sui_sdk_types::U256`].
18pub struct BigInt<T: sealed::Numeric = u64>(pub T);
19
20impl<'de, T: sealed::Numeric> Deserialize<'de> for BigInt<T> {
21    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
22    where
23        D: serde::Deserializer<'de>,
24    {
25        let s = <Cow<'_, str>>::deserialize(deserializer)?;
26        let value = s.parse().map_err(serde::de::Error::custom)?;
27        Ok(BigInt(value))
28    }
29}
30
31/// Restrict the types that can be used inside `BigInt`.
32mod sealed {
33    use std::fmt::Display;
34    use std::str::FromStr;
35
36    pub trait Numeric: FromStr<Err: Display> {}
37
38    impl Numeric for i8 {}
39    impl Numeric for i16 {}
40    impl Numeric for i32 {}
41    impl Numeric for i64 {}
42    impl Numeric for i128 {}
43    impl Numeric for isize {}
44    impl Numeric for u8 {}
45    impl Numeric for u16 {}
46    impl Numeric for u32 {}
47    impl Numeric for u64 {}
48    impl Numeric for u128 {}
49    impl Numeric for usize {}
50    impl Numeric for sui_sdk_types::U256 {}
51}
52
53/// `DateTime` scalar in Sui GraphQL schema.
54/// ISO-8601 Date and Time in UTC.
55pub type DateTime = chrono::DateTime<chrono::Utc>;
56
57#[cfg(test)]
58mod tests {
59    use super::BigInt;
60    use sui_sdk_types::U256;
61
62    #[test]
63    fn defaults_to_u64() {
64        let value: BigInt = serde_json::from_str(r#""18446744073709551615""#).unwrap();
65        assert_eq!(value.0, u64::MAX);
66    }
67
68    #[test]
69    fn supports_all_primitive_integer_types() {
70        macro_rules! check_types {
71            ($($type:ty),+ $(,)?) => {
72                $(
73                    let value: BigInt<$type> = serde_json::from_str(r#""1""#).unwrap();
74                    assert_eq!(value.0, 1);
75                )+
76            };
77        }
78
79        check_types!(
80            i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize
81        );
82    }
83
84    #[test]
85    fn supports_larger_integer_types() {
86        let value: BigInt<u128> =
87            serde_json::from_str(r#""340282366920938463463374607431768211455""#).unwrap();
88        assert_eq!(value.0, u128::MAX);
89
90        let value: BigInt<U256> = serde_json::from_str(
91            r#""115792089237316195423570985008687907853269984665640564039457584007913129639935""#,
92        )
93        .unwrap();
94        assert_eq!(value.0, U256::from_digits([u8::MAX; 32]));
95    }
96}