cynic/variables.rs
1//! Types & traits for working with GraphQL Variables
2
3use std::marker::PhantomData;
4
5use crate::queries::InputLiteral;
6
7/// The type of a variable
8#[derive(Debug, Clone, Copy)]
9pub enum VariableType {
10 /// A list of some VariableType
11 List(&'static VariableType),
12 /// Some VariableType that may be null
13 Nullable(&'static VariableType),
14 /// A type with the given name
15 Named(&'static str),
16}
17
18/// Allows a struct to be used as variables in a GraphQL query.
19///
20/// Users should not implement this themselves, and should use the
21/// `QueryVariables` derive. All the fields on a `QueryVariables` struct should
22/// be available as variables in the query, using `$variable_name` notation.
23pub trait QueryVariables {
24 /// A struct that determines which variables are available when using this
25 /// struct.
26 type Fields: QueryVariablesFields;
27
28 /// An associated constant that contains the variable names & their types.
29 ///
30 /// This is used to construct the query string we send to a server.
31 const VARIABLES: &'static [(&'static str, VariableType)];
32}
33
34/// Represents a set of named variables from an impl of `QueryVariables`.
35///
36/// Types that implement this trait are almost always autogenerated by
37/// `derive(QueryVariables)`
38pub trait QueryVariablesFields {}
39
40impl QueryVariables for () {
41 type Fields = ();
42
43 const VARIABLES: &'static [(&'static str, VariableType)] = &[];
44}
45
46impl QueryVariablesFields for () {}
47
48/// Allows a query variable struct to be converted to literals for easier inlining
49/// into a graphql document.
50///
51/// Cynic can derive this automatically or you can add it to a QueryVariables struct
52/// yourself.
53pub trait QueryVariableLiterals {
54 /// Gets an InputLiteral for the given variable from this set of variables
55 fn get(&self, variable_name: &str) -> Option<InputLiteral>;
56}
57
58#[doc(hidden)]
59/// A VariableDefinition.
60///
61/// These are returned by functions on the `Fields` associated type of a
62/// `QueryVariables` struct. But users shouldn't need to care about that.
63pub struct VariableDefinition<Variables, Type> {
64 pub name: &'static str,
65 phantom: PhantomData<fn() -> (Variables, Type)>,
66}
67
68impl<Variables, Type> VariableDefinition<Variables, Type> {
69 /// Create a new variable with the given name.
70 pub fn new(name: &'static str) -> Self {
71 VariableDefinition {
72 name,
73 phantom: PhantomData,
74 }
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use cynic::QueryVariableLiterals;
81
82 #[test]
83 fn query_variable_literals_is_object_safe() {
84 #[derive(QueryVariableLiterals)]
85 struct Blah {
86 x: String,
87 }
88
89 let _: Box<dyn QueryVariableLiterals> = Box::new(Blah { x: "hello".into() });
90 }
91}