1#[macro_export]
8macro_rules! doc_scalar {
9 ($ty:ty, $desc:literal) => {
10 $crate::async_graphql::scalar_internal!(
11 $ty,
12 ::std::stringify!($ty),
13 ::std::option::Option::Some(::std::string::ToString::to_string($desc)),
14 ::std::option::Option::None
15 );
16 };
17}
18
19#[derive(thiserror::Error, Debug)]
21#[allow(missing_docs)]
22pub enum BcsHexParseError {
23 #[error("Invalid BCS: {0}")]
24 Bcs(#[from] bcs::Error),
25 #[error("Invalid hexadecimal: {0}")]
26 Hex(#[from] hex::FromHexError),
27}
28
29#[macro_export]
34macro_rules! bcs_scalar {
35 ($ty:ty, $desc:literal) => {
36 impl $crate::async_graphql::ScalarType for $ty {
37 fn parse(
38 value: $crate::async_graphql::Value,
39 ) -> $crate::async_graphql::InputValueResult<Self> {
40 let hex: String = $crate::async_graphql::from_value(value)?;
41 let bytes = $crate::hex::decode(&hex)?;
42 let result = $crate::bcs::from_bytes(&bytes)?;
43 ::std::result::Result::Ok(result)
44 }
45
46 fn to_value(&self) -> $crate::async_graphql::Value {
47 let ::std::result::Result::Ok(bytes) = $crate::bcs::to_bytes(self) else {
48 return $crate::async_graphql::Value::Null;
49 };
50 let hex = $crate::hex::encode(&bytes);
51 $crate::async_graphql::to_value(hex)
52 .unwrap_or_else(|_| $crate::async_graphql::Value::Null)
53 }
54 }
55
56 impl $crate::async_graphql::InputType for $ty {
57 type RawValueType = Self;
58
59 fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
60 ::std::borrow::Cow::Borrowed(::std::stringify!($ty))
61 }
62
63 fn create_type_info(
64 registry: &mut $crate::async_graphql::registry::Registry,
65 ) -> ::std::string::String {
66 registry.create_input_type::<$ty, _>(
67 $crate::async_graphql::registry::MetaTypeId::Scalar,
68 |_| $crate::async_graphql::registry::MetaType::Scalar {
69 name: ::std::borrow::ToOwned::to_owned(::std::stringify!($ty)),
70 description: ::std::option::Option::Some(
71 ::std::string::ToString::to_string($desc),
72 ),
73 is_valid: ::std::option::Option::Some(::std::sync::Arc::new(|value| {
74 <$ty as $crate::async_graphql::ScalarType>::is_valid(value)
75 })),
76 visible: ::std::option::Option::None,
77 inaccessible: false,
78 tags: ::std::default::Default::default(),
79 specified_by_url: ::std::option::Option::None,
80 },
81 )
82 }
83
84 fn parse(
85 value: ::std::option::Option<$crate::async_graphql::Value>,
86 ) -> $crate::async_graphql::InputValueResult<Self> {
87 <$ty as $crate::async_graphql::ScalarType>::parse(value.unwrap_or_default())
88 }
89
90 fn to_value(&self) -> $crate::async_graphql::Value {
91 <$ty as $crate::async_graphql::ScalarType>::to_value(self)
92 }
93
94 fn as_raw_value(&self) -> ::std::option::Option<&Self::RawValueType> {
95 ::std::option::Option::Some(self)
96 }
97 }
98
99 impl $crate::async_graphql::OutputType for $ty {
100 fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
101 ::std::borrow::Cow::Borrowed(::std::stringify!($ty))
102 }
103
104 fn create_type_info(
105 registry: &mut $crate::async_graphql::registry::Registry,
106 ) -> ::std::string::String {
107 registry.create_output_type::<$ty, _>(
108 $crate::async_graphql::registry::MetaTypeId::Scalar,
109 |_| $crate::async_graphql::registry::MetaType::Scalar {
110 name: ::std::borrow::ToOwned::to_owned(::std::stringify!($ty)),
111 description: ::std::option::Option::Some(
112 ::std::string::ToString::to_string($desc),
113 ),
114 is_valid: ::std::option::Option::Some(::std::sync::Arc::new(|value| {
115 <$ty as $crate::async_graphql::ScalarType>::is_valid(value)
116 })),
117 visible: ::std::option::Option::None,
118 inaccessible: false,
119 tags: ::std::default::Default::default(),
120 specified_by_url: ::std::option::Option::None,
121 },
122 )
123 }
124
125 async fn resolve(
126 &self,
127 _: &$crate::async_graphql::ContextSelectionSet<'_>,
128 _field: &$crate::async_graphql::Positioned<
129 $crate::async_graphql::parser::types::Field,
130 >,
131 ) -> $crate::async_graphql::ServerResult<$crate::async_graphql::Value> {
132 ::std::result::Result::Ok($crate::async_graphql::ScalarType::to_value(self))
133 }
134 }
135
136 impl ::std::fmt::Display for $ty {
137 fn fmt(
138 &self,
139 f: &mut ::std::fmt::Formatter<'_>,
140 ) -> ::std::result::Result<(), ::std::fmt::Error> {
141 match $crate::bcs::to_bytes(self) {
142 ::std::result::Result::Ok(bytes) => {
143 ::std::fmt::Display::fmt(&$crate::hex::encode(&bytes), f)
144 }
145 ::std::result::Result::Err(_) => {
146 ::std::write!(f, "invalid {}", ::std::stringify!($ty))
147 }
148 }
149 }
150 }
151
152 impl ::std::str::FromStr for $ty {
153 type Err = $crate::BcsHexParseError;
154
155 fn from_str(s: &str) -> Result<Self, Self::Err> {
156 let bytes = $crate::hex::decode(s)?;
157 ::std::result::Result::Ok($crate::bcs::from_bytes(&bytes)?)
158 }
159 }
160 };
161}