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(transparent)]
24 BcsError(#[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 directive_invocations: ::std::default::Default::default(),
81 requires_scopes: ::std::default::Default::default(),
82 },
83 )
84 }
85
86 fn parse(
87 value: ::std::option::Option<$crate::async_graphql::Value>,
88 ) -> $crate::async_graphql::InputValueResult<Self> {
89 <$ty as $crate::async_graphql::ScalarType>::parse(value.unwrap_or_default())
90 }
91
92 fn to_value(&self) -> $crate::async_graphql::Value {
93 <$ty as $crate::async_graphql::ScalarType>::to_value(self)
94 }
95
96 fn as_raw_value(&self) -> ::std::option::Option<&Self::RawValueType> {
97 ::std::option::Option::Some(self)
98 }
99 }
100
101 impl $crate::async_graphql::OutputType for $ty {
102 fn type_name() -> ::std::borrow::Cow<'static, ::std::primitive::str> {
103 ::std::borrow::Cow::Borrowed(::std::stringify!($ty))
104 }
105
106 fn create_type_info(
107 registry: &mut $crate::async_graphql::registry::Registry,
108 ) -> ::std::string::String {
109 registry.create_output_type::<$ty, _>(
110 $crate::async_graphql::registry::MetaTypeId::Scalar,
111 |_| $crate::async_graphql::registry::MetaType::Scalar {
112 name: ::std::borrow::ToOwned::to_owned(::std::stringify!($ty)),
113 description: ::std::option::Option::Some(
114 ::std::string::ToString::to_string($desc),
115 ),
116 is_valid: ::std::option::Option::Some(::std::sync::Arc::new(|value| {
117 <$ty as $crate::async_graphql::ScalarType>::is_valid(value)
118 })),
119 visible: ::std::option::Option::None,
120 inaccessible: false,
121 tags: ::std::default::Default::default(),
122 specified_by_url: ::std::option::Option::None,
123 directive_invocations: ::std::default::Default::default(),
124 requires_scopes: ::std::default::Default::default(),
125 },
126 )
127 }
128
129 async fn resolve(
130 &self,
131 _: &$crate::async_graphql::ContextSelectionSet<'_>,
132 _field: &$crate::async_graphql::Positioned<
133 $crate::async_graphql::parser::types::Field,
134 >,
135 ) -> $crate::async_graphql::ServerResult<$crate::async_graphql::Value> {
136 ::std::result::Result::Ok($crate::async_graphql::ScalarType::to_value(self))
137 }
138 }
139
140 impl ::std::fmt::Display for $ty {
141 fn fmt(
142 &self,
143 f: &mut ::std::fmt::Formatter<'_>,
144 ) -> ::std::result::Result<(), ::std::fmt::Error> {
145 match $crate::bcs::to_bytes(self) {
146 ::std::result::Result::Ok(bytes) => {
147 ::std::fmt::Display::fmt(&$crate::hex::encode(&bytes), f)
148 }
149 ::std::result::Result::Err(_) => {
150 ::std::write!(f, "invalid {}", ::std::stringify!($ty))
151 }
152 }
153 }
154 }
155
156 impl ::std::str::FromStr for $ty {
157 type Err = $crate::BcsHexParseError;
158
159 fn from_str(s: &str) -> Result<Self, Self::Err> {
160 let bytes = $crate::hex::decode(s)?;
161 ::std::result::Result::Ok($crate::bcs::from_bytes(&bytes)?)
162 }
163 }
164 };
165}