use crate::{InputValueResult, Value};
pub trait ScalarType: Sized + Send {
fn parse(value: Value) -> InputValueResult<Self>;
fn is_valid(_value: &Value) -> bool {
true
}
fn to_value(&self) -> Value;
}
#[macro_export]
macro_rules! scalar {
($ty:ty, $name:expr, $desc:literal) => {
scalar_internal!($ty, stringify!($ty), Some($desc));
};
($ty:ty, $name:expr) => {
scalar_internal!($ty, stringify!($ty), None);
};
($ty:ty) => {
scalar_internal!($ty, stringify!($ty), None);
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! scalar_internal {
($ty:ty, $name:expr, $desc:expr) => {
impl $crate::Type for $ty {
fn type_name() -> ::std::borrow::Cow<'static, str> {
::std::borrow::Cow::Borrowed($name)
}
fn create_type_info(registry: &mut $crate::registry::Registry) -> String {
registry.create_type::<$ty, _>(|_| $crate::registry::MetaType::Scalar {
name: $name.into(),
description: $desc,
is_valid: |value| <$ty as $crate::ScalarType>::is_valid(value),
})
}
}
impl $crate::ScalarType for $ty {
fn parse(value: $crate::Value) -> $crate::InputValueResult<Self> {
Ok($crate::from_value(value)?)
}
fn to_value(&self) -> $crate::Value {
$crate::to_value(self).unwrap_or_else(|_| $crate::Value::Null)
}
}
impl $crate::InputValueType for $ty {
fn parse(value: Option<$crate::Value>) -> $crate::InputValueResult<Self> {
<$ty as $crate::ScalarType>::parse(value.unwrap_or_default())
}
fn to_value(&self) -> $crate::Value {
<$ty as $crate::ScalarType>::to_value(self)
}
}
#[$crate::async_trait::async_trait]
impl $crate::OutputValueType for $ty {
async fn resolve(
&self,
_: &$crate::ContextSelectionSet<'_>,
_field: &$crate::Positioned<$crate::parser::types::Field>,
) -> $crate::ServerResult<$crate::Value> {
Ok($crate::ScalarType::to_value(self))
}
}
};
}