iota_graphql_rpc/types/
uint53.rs1use std::fmt;
6
7use async_graphql::*;
8use iota_sdk_types::Version;
9use iota_types::iota_serde::BigInt;
10use serde::{Deserialize, Serialize};
11
12use crate::error::Error;
13
14pub(crate) const MAX_UINT53: u64 = (1 << 53) - 1;
16
17#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
18#[serde(try_from = "u64", into = "u64")]
19pub(crate) struct UInt53(u64);
20
21impl UInt53 {
22 pub(crate) fn new_unchecked(value: u64) -> Self {
26 Self(value)
27 }
28}
29
30#[Scalar(name = "UInt53")]
34impl ScalarType for UInt53 {
35 fn parse(value: Value) -> InputValueResult<Self> {
36 let Value::Number(n) = value else {
37 return Err(InputValueError::expected_type(value));
38 };
39
40 let Some(n) = n.as_u64() else {
41 return Err(InputValueError::custom("Expected an unsigned integer."));
42 };
43
44 Self::try_from(n)
45 .map_err(|_| InputValueError::custom("Value exceeds the maximum of UInt53 (2^53 - 1)."))
46 }
47
48 fn to_value(&self) -> Value {
49 Value::Number(self.0.into())
50 }
51}
52
53impl fmt::Display for UInt53 {
54 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
55 write!(f, "{}", self.0)
56 }
57}
58
59impl TryFrom<u64> for UInt53 {
60 type Error = Error;
61
62 fn try_from(value: u64) -> Result<Self, Self::Error> {
63 if value > MAX_UINT53 {
64 return Err(Error::Internal(format!(
65 "Value {value} exceeds the maximum of UInt53 (2^53 - 1)"
66 )));
67 }
68 Ok(Self(value))
69 }
70}
71
72impl From<u32> for UInt53 {
73 fn from(value: u32) -> Self {
74 Self(value.into())
75 }
76}
77
78impl From<UInt53> for Version {
79 fn from(value: UInt53) -> Self {
80 Version::from(value.0)
81 }
82}
83
84impl From<UInt53> for BigInt<u64> {
85 fn from(value: UInt53) -> Self {
86 BigInt::from(value.0)
87 }
88}
89
90impl From<UInt53> for u64 {
91 fn from(value: UInt53) -> Self {
92 value.0
93 }
94}
95
96impl From<UInt53> for i64 {
97 fn from(value: UInt53) -> Self {
98 value.0 as i64
99 }
100}
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105
106 #[test]
107 fn parse_bounds() {
108 assert_eq!(
109 <UInt53 as ScalarType>::parse(Value::Number(MAX_UINT53.into())).unwrap(),
110 UInt53(MAX_UINT53)
111 );
112 assert!(<UInt53 as ScalarType>::parse(Value::Number((MAX_UINT53 + 1).into())).is_err());
113 assert!(<UInt53 as ScalarType>::parse(Value::Number((-1).into())).is_err());
114 assert!(<UInt53 as ScalarType>::parse(Value::String("1".to_string())).is_err());
115 }
116
117 #[test]
118 fn try_from_bounds() {
119 assert_eq!(UInt53::try_from(MAX_UINT53).unwrap(), UInt53(MAX_UINT53));
120 assert!(UInt53::try_from(MAX_UINT53 + 1).is_err());
121 }
122}