Skip to main content

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}