Refactor value!
macro position [skip ci]
This commit is contained in:
parent
b716a45215
commit
b28acbd96d
5 changed files with 103 additions and 97 deletions
|
@ -1,8 +1,10 @@
|
|||
use crate::{behavior, resolve};
|
||||
|
||||
pub use crate::{
|
||||
ast::InputValue, graphql_value as value, macros::input_value,
|
||||
resolve::Type, value::Value,
|
||||
ast::InputValue,
|
||||
macros::{input_value, value},
|
||||
resolve::Type,
|
||||
value::Value,
|
||||
};
|
||||
|
||||
pub trait Interface<S>
|
||||
|
|
|
@ -75,8 +75,8 @@ pub use crate::{
|
|||
},
|
||||
introspection::IntrospectionFormat,
|
||||
macros::{
|
||||
input_value as graphql_input_value,
|
||||
helper::subscription::{ExtractTypeFromStream, IntoFieldResult},
|
||||
input_value as graphql_input_value, value as graphql_value,
|
||||
},
|
||||
parser::{ParseError, ScalarToken, Spanning},
|
||||
schema::{
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
/// - [`InputValue::Enum`] is constructed with `ident`, so to capture outer
|
||||
/// variable as [`InputValue::Scalar`] surround it with parens: `(var)`.
|
||||
/// ```rust
|
||||
/// # use juniper::{graphql, graphql_value};
|
||||
/// # use juniper::graphql;
|
||||
/// #
|
||||
/// # type InputValue = graphql::InputValue;
|
||||
/// # type Value = graphql::Value;
|
||||
|
|
|
@ -7,10 +7,9 @@ pub mod helper;
|
|||
pub mod reflect;
|
||||
|
||||
mod input_value;
|
||||
#[macro_use]
|
||||
mod graphql_value;
|
||||
mod value;
|
||||
#[macro_use]
|
||||
mod graphql_vars;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use self::input_value::input_value;
|
||||
pub use self::{input_value::input_value, value::value};
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
//! [`graphql_value!`] macro implementation.
|
||||
//!
|
||||
//! [`graphql_value!`]: graphql_value
|
||||
//! [`value!`] macro implementation.
|
||||
|
||||
/// Constructs [`Value`]s via JSON-like syntax.
|
||||
/// Constructs [`graphql::Value`]s via JSON-like syntax.
|
||||
///
|
||||
/// [`Value`] objects are used mostly when creating custom errors from fields.
|
||||
/// [`graphql::Value`] objects are used mostly when creating custom errors from
|
||||
/// fields.
|
||||
///
|
||||
/// [`Value::Object`] key should implement [`AsRef`]`<`[`str`]`>`.
|
||||
/// ```rust
|
||||
/// # use juniper::{graphql_value, Value};
|
||||
/// # use juniper::graphql;
|
||||
/// #
|
||||
/// let code = 200;
|
||||
/// let features = ["key", "value"];
|
||||
///
|
||||
/// let value: Value = graphql_value!({
|
||||
/// let value: graphql::Value = graphql::value!({
|
||||
/// "code": code,
|
||||
/// "success": code == 200,
|
||||
/// "payload": {
|
||||
|
@ -26,94 +25,93 @@
|
|||
///
|
||||
/// Resulting JSON will look just like what you passed in.
|
||||
/// ```rust
|
||||
/// # use juniper::{graphql_value, DefaultScalarValue, Value};
|
||||
/// # use juniper::graphql;
|
||||
/// #
|
||||
/// # type V = Value<DefaultScalarValue>;
|
||||
/// # type V = graphql::Value;
|
||||
/// #
|
||||
/// # let _: V =
|
||||
/// graphql_value!(null);
|
||||
/// graphql::value!(null);
|
||||
/// # let _: V =
|
||||
/// graphql_value!(1234);
|
||||
/// graphql::value!(1234);
|
||||
/// # let _: V =
|
||||
/// graphql_value!("test");
|
||||
/// graphql::value!("test");
|
||||
/// # let _: V =
|
||||
/// graphql_value!([1234, "test", true]);
|
||||
/// graphql::value!([1234, "test", true]);
|
||||
/// # let _: V =
|
||||
/// graphql_value!({"key": "value", "foo": 1234});
|
||||
/// graphql::value!({"key": "value", "foo": 1234});
|
||||
/// ```
|
||||
///
|
||||
/// [`Value`]: crate::Value
|
||||
/// [`Value::Object`]: crate::Value::Object
|
||||
#[macro_export]
|
||||
macro_rules! graphql_value {
|
||||
/// [`graphql::Value`]: crate::graphql::Value
|
||||
/// [`Value::Object`]: crate::graphql::Value::Object
|
||||
macro_rules! value {
|
||||
///////////
|
||||
// Array //
|
||||
///////////
|
||||
|
||||
// Done with trailing comma.
|
||||
(@array [$($elems:expr,)*]) => {
|
||||
$crate::Value::list(vec![
|
||||
$crate::graphql::Value::list(::std::vec![
|
||||
$( $elems, )*
|
||||
])
|
||||
};
|
||||
|
||||
// Done without trailing comma.
|
||||
(@array [$($elems:expr),*]) => {
|
||||
$crate::Value::list(vec![
|
||||
$( $crate::graphql_value!($elems), )*
|
||||
$crate::graphql::Value::list(::std::vec![
|
||||
$( $crate::graphql::value!($elems), )*
|
||||
])
|
||||
};
|
||||
|
||||
// Next element is `null`.
|
||||
(@array [$($elems:expr,)*] null $($rest:tt)*) => {
|
||||
$crate::graphql_value!(
|
||||
@array [$($elems,)* $crate::graphql_value!(null)] $($rest)*
|
||||
$crate::graphql::value!(
|
||||
@array [$($elems,)* $crate::graphql::value!(null)] $($rest)*
|
||||
)
|
||||
};
|
||||
|
||||
// Next element is `None`.
|
||||
(@array [$($elems:expr,)*] None $($rest:tt)*) => {
|
||||
$crate::graphql_value!(
|
||||
@array [$($elems,)* $crate::graphql_value!(None)] $($rest)*
|
||||
$crate::graphql::value!(
|
||||
@array [$($elems,)* $crate::graphql::value!(None)] $($rest)*
|
||||
)
|
||||
};
|
||||
|
||||
// Next element is an array.
|
||||
(@array [$($elems:expr,)*] [$($array:tt)*] $($rest:tt)*) => {
|
||||
$crate::graphql_value!(
|
||||
@array [$($elems,)* $crate::graphql_value!([$($array)*])] $($rest)*
|
||||
$crate::graphql::value!(
|
||||
@array [$($elems,)* $crate::graphql::value!([$($array)*])] $($rest)*
|
||||
)
|
||||
};
|
||||
|
||||
// Next element is a map.
|
||||
(@array [$($elems:expr,)*] {$($map:tt)*} $($rest:tt)*) => {
|
||||
$crate::graphql_value!(
|
||||
@array [$($elems,)* $crate::graphql_value!({$($map)*})] $($rest)*
|
||||
$crate::graphql::value!(
|
||||
@array [$($elems,)* $crate::graphql::value!({$($map)*})] $($rest)*
|
||||
)
|
||||
};
|
||||
|
||||
// Next element is an expression followed by comma.
|
||||
(@array [$($elems:expr,)*] $next:expr, $($rest:tt)*) => {
|
||||
$crate::graphql_value!(
|
||||
@array [$($elems,)* $crate::graphql_value!($next),] $($rest)*
|
||||
$crate::graphql::value!(
|
||||
@array [$($elems,)* $crate::graphql::value!($next),] $($rest)*
|
||||
)
|
||||
};
|
||||
|
||||
// Last element is an expression with no trailing comma.
|
||||
(@array [$($elems:expr,)*] $last:expr) => {
|
||||
$crate::graphql_value!(
|
||||
@array [$($elems,)* $crate::graphql_value!($last)]
|
||||
$crate::graphql::value!(
|
||||
@array [$($elems,)* $crate::graphql::value!($last)]
|
||||
)
|
||||
};
|
||||
|
||||
// Comma after the most recent element.
|
||||
(@array [$($elems:expr),*] , $($rest:tt)*) => {
|
||||
$crate::graphql_value!(@array [$($elems,)*] $($rest)*)
|
||||
$crate::graphql::value!(@array [$($elems,)*] $($rest)*)
|
||||
};
|
||||
|
||||
// Unexpected token after most recent element.
|
||||
(@array [$($elems:expr),*] $unexpected:tt $($rest:tt)*) => {
|
||||
$crate::graphql_value!(@unexpected $unexpected)
|
||||
$crate::graphql::value!(@unexpected $unexpected)
|
||||
};
|
||||
|
||||
////////////
|
||||
|
@ -126,12 +124,12 @@ macro_rules! graphql_value {
|
|||
// Insert the current entry followed by trailing comma.
|
||||
(@object $object:ident [$($key:tt)+] ($value:expr) , $($rest:tt)*) => {
|
||||
let _ = $object.add_field(($($key)+), $value);
|
||||
$crate::graphql_value!(@object $object () ($($rest)*) ($($rest)*));
|
||||
$crate::graphql::value!(@object $object () ($($rest)*) ($($rest)*));
|
||||
};
|
||||
|
||||
// Current entry followed by unexpected token.
|
||||
(@object $object:ident [$($key:tt)+] ($value:expr) $unexpected:tt $($rest:tt)*) => {
|
||||
$crate::graphql_value!(@unexpected $unexpected);
|
||||
$crate::graphql::value!(@unexpected $unexpected);
|
||||
};
|
||||
|
||||
// Insert the last entry without trailing comma.
|
||||
|
@ -141,97 +139,97 @@ macro_rules! graphql_value {
|
|||
|
||||
// Next value is `null`.
|
||||
(@object $object:ident ($($key:tt)+) (: null $($rest:tt)*) $copy:tt) => {
|
||||
$crate::graphql_value!(
|
||||
$crate::graphql::value!(
|
||||
@object $object
|
||||
[$($key)+]
|
||||
($crate::graphql_value!(null)) $($rest)*
|
||||
($crate::graphql::value!(null)) $($rest)*
|
||||
);
|
||||
};
|
||||
|
||||
// Next value is `None`.
|
||||
(@object $object:ident ($($key:tt)+) (: None $($rest:tt)*) $copy:tt) => {
|
||||
$crate::graphql_value!(
|
||||
$crate::graphql::value!(
|
||||
@object $object
|
||||
[$($key)+]
|
||||
($crate::graphql_value!(None)) $($rest)*
|
||||
($crate::graphql::value!(None)) $($rest)*
|
||||
);
|
||||
};
|
||||
|
||||
// Next value is an array.
|
||||
(@object $object:ident ($($key:tt)+) (: [$($array:tt)*] $($rest:tt)*) $copy:tt) => {
|
||||
$crate::graphql_value!(
|
||||
$crate::graphql::value!(
|
||||
@object $object
|
||||
[$($key)+]
|
||||
($crate::graphql_value!([$($array)*])) $($rest)*
|
||||
($crate::graphql::value!([$($array)*])) $($rest)*
|
||||
);
|
||||
};
|
||||
|
||||
// Next value is a map.
|
||||
(@object $object:ident ($($key:tt)+) (: {$($map:tt)*} $($rest:tt)*) $copy:tt) => {
|
||||
$crate::graphql_value!(
|
||||
$crate::graphql::value!(
|
||||
@object $object
|
||||
[$($key)+]
|
||||
($crate::graphql_value!({$($map)*})) $($rest)*
|
||||
($crate::graphql::value!({$($map)*})) $($rest)*
|
||||
);
|
||||
};
|
||||
|
||||
// Next value is an expression followed by comma.
|
||||
(@object $object:ident ($($key:tt)+) (: $value:expr , $($rest:tt)*) $copy:tt) => {
|
||||
$crate::graphql_value!(
|
||||
$crate::graphql::value!(
|
||||
@object $object
|
||||
[$($key)+]
|
||||
($crate::graphql_value!($value)) , $($rest)*
|
||||
($crate::graphql::value!($value)) , $($rest)*
|
||||
);
|
||||
};
|
||||
|
||||
// Last value is an expression with no trailing comma.
|
||||
(@object $object:ident ($($key:tt)+) (: $value:expr) $copy:tt) => {
|
||||
$crate::graphql_value!(
|
||||
$crate::graphql::value!(
|
||||
@object $object
|
||||
[$($key)+]
|
||||
($crate::graphql_value!($value))
|
||||
($crate::graphql::value!($value))
|
||||
);
|
||||
};
|
||||
|
||||
// Missing value for last entry. Trigger a reasonable error message.
|
||||
(@object $object:ident ($($key:tt)+) (:) $copy:tt) => {
|
||||
// "unexpected end of macro invocation"
|
||||
$crate::graphql_value!();
|
||||
$crate::graphql::value!();
|
||||
};
|
||||
|
||||
// Missing colon and value for last entry. Trigger a reasonable error
|
||||
// message.
|
||||
(@object $object:ident ($($key:tt)+) () $copy:tt) => {
|
||||
// "unexpected end of macro invocation"
|
||||
$crate::graphql_value!();
|
||||
$crate::graphql::value!();
|
||||
};
|
||||
|
||||
// Misplaced colon. Trigger a reasonable error message.
|
||||
(@object $object:ident () (: $($rest:tt)*) ($colon:tt $($copy:tt)*)) => {
|
||||
// Takes no arguments so "no rules expected the token `:`".
|
||||
$crate::graphql_value!(@unexpected $colon);
|
||||
$crate::graphql::value!(@unexpected $colon);
|
||||
};
|
||||
|
||||
// Found a comma inside a key. Trigger a reasonable error message.
|
||||
(@object $object:ident ($($key:tt)*) (, $($rest:tt)*) ($comma:tt $($copy:tt)*)) => {
|
||||
// Takes no arguments so "no rules expected the token `,`".
|
||||
$crate::graphql_value!(@unexpected $comma);
|
||||
$crate::graphql::value!(@unexpected $comma);
|
||||
};
|
||||
|
||||
// Key is fully parenthesized. This avoids `clippy::double_parens` false
|
||||
// positives because the parenthesization may be necessary here.
|
||||
(@object $object:ident () (($key:expr) : $($rest:tt)*) $copy:tt) => {
|
||||
$crate::graphql_value!(@object $object ($key) (: $($rest)*) (: $($rest)*));
|
||||
$crate::graphql::value!(@object $object ($key) (: $($rest)*) (: $($rest)*));
|
||||
};
|
||||
|
||||
// Refuse to absorb colon token into key expression.
|
||||
(@object $object:ident ($($key:tt)*) (: $($unexpected:tt)+) $copy:tt) => {
|
||||
$crate::graphql_value!(@unexpected $($unexpected)+);
|
||||
$crate::graphql::value!(@unexpected $($unexpected)+);
|
||||
};
|
||||
|
||||
// Munch a token into the current key.
|
||||
(@object $object:ident ($($key:tt)*) ($tt:tt $($rest:tt)*) $copy:tt) => {
|
||||
$crate::graphql_value!(
|
||||
$crate::graphql::value!(
|
||||
@object $object
|
||||
($($key)* $tt)
|
||||
($($rest)*) ($($rest)*)
|
||||
|
@ -249,63 +247,70 @@ macro_rules! graphql_value {
|
|||
//////////////
|
||||
|
||||
([ $($arr:tt)* ]$(,)?) => {
|
||||
$crate::graphql_value!(@array [] $($arr)*)
|
||||
$crate::graphql::value!(@array [] $($arr)*)
|
||||
};
|
||||
|
||||
({}$(,)?) => {
|
||||
$crate::Value::object($crate::Object::with_capacity(0))
|
||||
$crate::graphql::Value::object($crate::Object::with_capacity(0))
|
||||
};
|
||||
|
||||
({ $($map:tt)+ }$(,)?) => {
|
||||
$crate::Value::object({
|
||||
$crate::graphql::Value::object({
|
||||
let mut object = $crate::Object::with_capacity(0);
|
||||
$crate::graphql_value!(@object object () ($($map)*) ($($map)*));
|
||||
$crate::graphql::value!(@object object () ($($map)*) ($($map)*));
|
||||
object
|
||||
})
|
||||
};
|
||||
|
||||
(null$(,)?) => ($crate::Value::null());
|
||||
(null$(,)?) => ($crate::graphql::Value::null());
|
||||
|
||||
(None$(,)?) => ($crate::Value::null());
|
||||
(None$(,)?) => ($crate::graphql::Value::null());
|
||||
|
||||
($e:expr$(,)?) => ($crate::Value::from($e));
|
||||
($e:expr$(,)?) => ($crate::graphql::Value::from($e));
|
||||
}
|
||||
|
||||
#[doc(inline)]
|
||||
pub(super) use value;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
type V = crate::Value;
|
||||
use crate::graphql;
|
||||
|
||||
use super::value;
|
||||
|
||||
type V = graphql::Value;
|
||||
|
||||
#[test]
|
||||
fn null() {
|
||||
assert_eq!(graphql_value!(null), V::Null);
|
||||
assert_eq!(value!(null), V::Null);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scalar() {
|
||||
let val = 42;
|
||||
|
||||
assert_eq!(graphql_value!(1), V::scalar(1));
|
||||
assert_eq!(graphql_value!("val"), V::scalar("val"));
|
||||
assert_eq!(graphql_value!(1.34), V::scalar(1.34));
|
||||
assert_eq!(graphql_value!(false), V::scalar(false));
|
||||
assert_eq!(graphql_value!(1 + 2), V::scalar(3));
|
||||
assert_eq!(graphql_value!(val), V::scalar(42));
|
||||
assert_eq!(value!(1), V::scalar(1));
|
||||
assert_eq!(value!("val"), V::scalar("val"));
|
||||
assert_eq!(value!(1.34), V::scalar(1.34));
|
||||
assert_eq!(value!(false), V::scalar(false));
|
||||
assert_eq!(value!(1 + 2), V::scalar(3));
|
||||
assert_eq!(value!(val), V::scalar(42));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list() {
|
||||
let val = 42;
|
||||
|
||||
assert_eq!(graphql_value!([]), V::list(vec![]));
|
||||
assert_eq!(value!([]), V::list(vec![]));
|
||||
|
||||
assert_eq!(graphql_value!([null]), V::list(vec![V::Null]));
|
||||
assert_eq!(value!([null]), V::list(vec![V::Null]));
|
||||
|
||||
assert_eq!(graphql_value!([1]), V::list(vec![V::scalar(1)]));
|
||||
assert_eq!(graphql_value!([1 + 2]), V::list(vec![V::scalar(3)]));
|
||||
assert_eq!(graphql_value!([val]), V::list(vec![V::scalar(42)]));
|
||||
assert_eq!(value!([1]), V::list(vec![V::scalar(1)]));
|
||||
assert_eq!(value!([1 + 2]), V::list(vec![V::scalar(3)]));
|
||||
assert_eq!(value!([val]), V::list(vec![V::scalar(42)]));
|
||||
|
||||
assert_eq!(
|
||||
graphql_value!([1, [2], 3]),
|
||||
value!([1, [2], 3]),
|
||||
V::list(vec![
|
||||
V::scalar(1),
|
||||
V::list(vec![V::scalar(2)]),
|
||||
|
@ -313,7 +318,7 @@ mod tests {
|
|||
]),
|
||||
);
|
||||
assert_eq!(
|
||||
graphql_value!(["string", [2 + 3], true]),
|
||||
value!(["string", [2 + 3], true]),
|
||||
V::list(vec![
|
||||
V::scalar("string"),
|
||||
V::list(vec![V::scalar(5)]),
|
||||
|
@ -327,31 +332,31 @@ mod tests {
|
|||
let val = 42;
|
||||
|
||||
assert_eq!(
|
||||
graphql_value!({}),
|
||||
value!({}),
|
||||
V::object(Vec::<(String, _)>::new().into_iter().collect()),
|
||||
);
|
||||
assert_eq!(
|
||||
graphql_value!({ "key": null }),
|
||||
value!({ "key": null }),
|
||||
V::object(vec![("key", V::Null)].into_iter().collect()),
|
||||
);
|
||||
assert_eq!(
|
||||
graphql_value!({ "key": 123 }),
|
||||
value!({ "key": 123 }),
|
||||
V::object(vec![("key", V::scalar(123))].into_iter().collect()),
|
||||
);
|
||||
assert_eq!(
|
||||
graphql_value!({ "key": 1 + 2 }),
|
||||
value!({ "key": 1 + 2 }),
|
||||
V::object(vec![("key", V::scalar(3))].into_iter().collect()),
|
||||
);
|
||||
assert_eq!(
|
||||
graphql_value!({ "key": [] }),
|
||||
value!({ "key": [] }),
|
||||
V::object(vec![("key", V::list(vec![]))].into_iter().collect()),
|
||||
);
|
||||
assert_eq!(
|
||||
graphql_value!({ "key": [null] }),
|
||||
value!({ "key": [null] }),
|
||||
V::object(vec![("key", V::list(vec![V::Null]))].into_iter().collect()),
|
||||
);
|
||||
assert_eq!(
|
||||
graphql_value!({ "key": [1] }),
|
||||
value!({ "key": [1] }),
|
||||
V::object(
|
||||
vec![("key", V::list(vec![V::scalar(1)]))]
|
||||
.into_iter()
|
||||
|
@ -359,7 +364,7 @@ mod tests {
|
|||
),
|
||||
);
|
||||
assert_eq!(
|
||||
graphql_value!({ "key": [1 + 2] }),
|
||||
value!({ "key": [1 + 2] }),
|
||||
V::object(
|
||||
vec![("key", V::list(vec![V::scalar(3)]))]
|
||||
.into_iter()
|
||||
|
@ -367,7 +372,7 @@ mod tests {
|
|||
),
|
||||
);
|
||||
assert_eq!(
|
||||
graphql_value!({ "key": [val] }),
|
||||
value!({ "key": [val] }),
|
||||
V::object(
|
||||
vec![("key", V::list(vec![V::scalar(42)]))]
|
||||
.into_iter()
|
||||
|
@ -380,8 +385,8 @@ mod tests {
|
|||
fn option() {
|
||||
let val = Some(42);
|
||||
|
||||
assert_eq!(graphql_value!(None), V::Null);
|
||||
assert_eq!(graphql_value!(Some(42)), V::scalar(42));
|
||||
assert_eq!(graphql_value!(val), V::scalar(42));
|
||||
assert_eq!(value!(None), V::Null);
|
||||
assert_eq!(value!(Some(42)), V::scalar(42));
|
||||
assert_eq!(value!(val), V::scalar(42));
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue